2

Esta obra de ´scar Belmonte et al. est´ bajo una licencia Creative O a Commons Reconocimiento-NoComercial-CompartirIgual 3.0 Unported

´ Indice general
1. Introducci´n o 1.1. Origen del lenguaje de programaci´n Java . . . . . . . . . . . . . o 1.2. Caracter´ ıstica de Java . . . . . . . . . . . . . . . . . . . . . . . . 1.3. El entorno de desarrollo integrado Eclipse . . . . . . . . . . . . . 1.3.1. Principales caracter´ ısticas del entorno de desarrollo Eclipse 1.3.2. Descarga e instalaci´n de Eclipse . . . . . . . . . . . . . . o 1.3.3. Configurando el aspecto de Eclipse: Perspectivas y Vistas 1.3.4. El primer ejemplo . . . . . . . . . . . . . . . . . . . . . . 1.4. Herramientas de desarrollo . . . . . . . . . . . . . . . . . . . . . . 1.4.1. A˜adiendo nueva funcionalidad a Eclipse: los plug-ins . . n 2. Clases 2.1. Definici´n de una clase . . . . . . . . . . . . . . o 2.2. Miembros de una clase . . . . . . . . . . . . . . 2.2.1. Atributos de una clase . . . . . . . . . . 2.2.2. M´todos de una clase. . . . . . . . . . . e 2.2.3. Constructores. . . . . . . . . . . . . . . 2.2.4. Sobrecarga de m´todos y constructores . e 2.3. Tipos de datos en Java. . . . . . . . . . . . . . 2.3.1. Arrays de datos en Java. . . . . . . . . . 2.4. Estructuras de control. . . . . . . . . . . . . . . 2.4.1. Estructuras de control de repetici´n. . . o 2.4.2. Estructuras de control de selecci´n. . . . o 2.5. Modificadores de acceso. . . . . . . . . . . . . . 2.6. Modificadores static y final. . . . . . . . . . 2.7. El recolector de basura. . . . . . . . . . . . . . 2.8. Finalizaci´n. . . . . . . . . . . . . . . . . . . . o 2.9. Comentarios. Comentarios de documentaci´n. . o 13 13 14 15 16 16 16 18 21 22 23 24 25 25 26 28 32 33 34 36 37 39 40 42 43 44 45 51 52 52 54 56 59 59 60 61

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

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

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

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

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

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

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

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

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

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

3. Herencia e Interfaces 3.1. Herencia. . . . . . . . . . . . . . . . . . . . . . . . . 3.2. Extensi´n de una clase. . . . . . . . . . . . . . . . . o 3.2.1. Sobrescribir atributos. . . . . . . . . . . . . . 3.2.2. Sobrescribir m´todos. . . . . . . . . . . . . . e 3.2.3. La palabra reservada super. . . . . . . . . . . 3.2.4. El constructor por defecto y la clase Object. 3.2.5. El operador instanceof. . . . . . . . . . . . 3.2.6. El modificador final. . . . . . . . . . . . . . 3

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

4 3.2.7. M´todos static. . . . e Clases abstractas. . . . . . . . Interfaces. . . . . . . . . . . . Enumeraciones. . . . . . . . . Paquetes en Java. . . . . . . . Clases e interface anidados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

´ INDICE GENERAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 63 65 68 69 71 75 76 76 77 78 82 84 87 87 88 88 91 93 94 94 95 95 96 98 99 100 101 102 103 105 106 107 108 109 110 110 110 112 117 118 120 120 121 122

3.3. 3.4. 3.5. 3.6. 3.7.

4. Subversion 4.1. ¿Qu´ es un sistema de control de versiones? . . e 4.2. Principales caracter´ ısticas de Subversion . . . . 4.3. Creaci´n de un repositorio . . . . . . . . . . . . o 4.4. Trabajo con repositorios . . . . . . . . . . . . . 4.4.1. Obteniendo informaci´n del repositorio o 4.5. Integraci´n con Eclipse . . . . . . . . . . . . . . o 5. Excepciones 5.1. ¿Qu´ es una excepci´n? . . . . . e o 5.1.1. Tipos de excepciones . . . 5.2. C´mo se gestiona una excepci´n o o 5.3. Creaci´n de excepciones propias . o

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

6. Pruebas unitarias con JUnit 6.1. ¿Qu´ son las pruebas unitarias? . . . . . . . . . . . . . . . . . e 6.1.1. Principios FIRST para el dise˜o de pruebas unitarias n 6.2. Pruebas unitarias con JUnit . . . . . . . . . . . . . . . . . . . 6.2.1. Creaci´n de clases de prueba . . . . . . . . . . . . . . o 6.2.2. La anotaci´n @Test . . . . . . . . . . . . . . . . . . . o 6.2.3. Las anotaciones @Before y @After . . . . . . . . . . . 6.2.4. Las anotaciones @BeforeClass y @AfterClass . . . . 6.2.5. Pruebas con bater´ de datos de entrada . . . . . . . . ıa 6.2.6. Ejecutar varias clases de prueba. Test Suites . . . . . 6.3. Cobertura de las pruebas . . . . . . . . . . . . . . . . . . . . 6.3.1. EclEmma y su plug-in para Eclipse . . . . . . . . . . . 7. Entrada y Salida 7.1. Flujos (Streams) . . . . . . . . . . . . . . . . 7.2. Flujos de bytes . . . . . . . . . . . . . . . . . 7.3. Flujos de caracteres . . . . . . . . . . . . . . 7.4. Conexi´n entre flujos de bytes y de caracteres o 7.5. El sistema de ficheros y flujos a ficheros . . . 7.5.1. El sistema de ficheros . . . . . . . . . 7.5.2. Flujos a ficheros . . . . . . . . . . . . 7.6. Serializaci´n . . . . . . . . . . . . . . . . . . . o

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

. . . . . . . .

8. Algunas clases de utilidad del paquete est´ndar a 8.1. La clase Scanner . . . . . . . . . . . . . . . . . . . 8.2. Trabajo con cadenas de caracteres . . . . . . . . . 8.2.1. La clase String . . . . . . . . . . . . . . . 8.2.2. Las clases StringBuffer y StringBuilder 8.3. Clases recubridoras . . . . . . . . . . . . . . . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

. . . . .

´ INDICE GENERAL 8.4. Colecciones . . . . . . . . . . . . . . . . . . . . . . 8.5. Trabajo con fechas . . . . . . . . . . . . . . . . . . 8.5.1. La clase Date . . . . . . . . . . . . . . . . . 8.5.2. Las clases Calendar y GregorianCalendar 8.6. Matem´ticas . . . . . . . . . . . . . . . . . . . . . a 8.6.1. La clase Math . . . . . . . . . . . . . . . . . 8.6.2. La clase Random . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5 124 128 128 129 129 129 130 133 133 134 135 138 139 139 141 143 144 144 145 145 146 146 147 148 150 151 151 153 154 155 155 157 162 162 162 163 164 166 166 168 173 173 174 175 176

9. Programaci´n con gen´ricos o e 9.1. ¿Qu´ son los tipos de datos gen´ricos? . . . . . . . . . e e 9.2. M´todos gen´ricos . . . . . . . . . . . . . . . . . . . . e e 9.3. Clases gen´ricas . . . . . . . . . . . . . . . . . . . . . . e 9.4. Ampliaci´n del tipo gen´rico . . . . . . . . . . . . . . o e 9.4.1. Tipos gen´ricos con l´ e ımite superior . . . . . . . 9.4.2. Comodines . . . . . . . . . . . . . . . . . . . . 9.5. Borrado de tipo y compatibilidad con c´digo heredado o 10.Construcci´n de proyectos con Ant o 10.1. Qu´ es Ant . . . . . . . . . . . . . . . . . e 10.2. Definici´n del proyecto . . . . . . . . . . . o 10.2.1. Objetivos . . . . . . . . . . . . . . 10.2.2. Tareas . . . . . . . . . . . . . . . . 10.3. Compilar el c´digo fuente de un proyecto o 10.4. Propiedades . . . . . . . . . . . . . . . . . 10.5. Estructuras path-like . . . . . . . . . . . 10.6. Ejecuci´n de las Pruebas Unitarias . . . . o 10.7. Generaci´n de la documentaci´n . . . . . o o 10.8. Empaquetado de la aplicaci´n . . . . . . . o 10.9. Ejecuci´n y limpieza . . . . . . . . . . . . o

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

. . . . . . . . . . .

11.Interfaces gr´ficas de usuario a 11.1. APIs para la programaci´n de interfaces gr´ficos de usuario en o a Java: AWT y Swing . . . . . . . . . . . . . . . . . . . . . . . . . 11.2. Contenedores y Componentes . . . . . . . . . . . . . . . . . . . . 11.3. Gestores de Aspecto (Layout Managers) . . . . . . . . . . . . . . 11.4. Detecci´n de eventos: Escuchadores . . . . . . . . . . . . . . . . . o 11.5. Algunos componentes Swing . . . . . . . . . . . . . . . . . . . . . 11.5.1. JLabel, muestra texto o iconos . . . . . . . . . . . . . . . 11.5.2. JButton, botones que el usuario puede pulsar . . . . . . . 11.5.3. JTextField, campos de introducci´n de texto . . . . . . . o 11.5.4. JRadioButton, botones de opciones . . . . . . . . . . . . 11.5.5. JCheckBox, botones de selecci´n m´ltiple . . . . . . . . . o u 11.5.6. JList, listas de selecci´n . . . . . . . . . . . . . . . . . . o 11.6. El patr´n de dise˜o Modelo/Vista/Controlador . . . . . . . . . . o n 12.Applets 12.1. ¿Qu´ son los Applets? . . . . . . . . . . . . e 12.2. Ciclo de vida de un Applet . . . . . . . . . 12.3. C´digo HTML para contener un Applet . . o 12.4. Lectura de par´metros de la p´gina HTML a a

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

. . . .

.1. . . . . . . 13. . . . . . . . . .1. .2. . . . .2. . . . . Sockets bajo el protocolo TCP 15. . e n 16. . . .2. .2. . . . . . . . ¿Qu´ es un hilo? Utilidades. . . 210 o 14. . . . . . Situaci´n que intenta resolver . . . .1. . 13. . . . . . . . . . . . . . . . . . . . . . . . . Ciclo de vida de un hilo .2. . o 13. . El patr´n de dise˜o Factory Method . . . . . . . .2. .1. . . . . . . . . . .2.4. . . . . . 211 o o 14. . . . . . . . . . . . .6. . . . . . .2. . . . . 15. ¿Qu´ es el acoplamiento entre clases y por e 16.2. . . . . . . . . 218 o 15. 215 14.2. ¿Qu´ es una URL? . . . 16. . . . Creaci´n de un Hilo mediante una clase interna . . . . 209 o 14.6. . .5. . .3. . . . .6 ´ INDICE GENERAL 12. Trabajar con MyLyn . . ¿Qu´ son los patrones de dise˜o? . . Creaci´n de un Hilo mediante una clase interna an´nima . . . Trabajo con MyLyn y Bugzilla desde Eclipse . . . .2. . . . . . . 215 o 14. . . .7. . . . Sincronizaci´n . . . . . . . . . . .3.6. . 13. . . . . . .1. . .1. 181 182 182 182 188 188 188 195 199 201 201 14. . . . . 16. . . . . .2. . . . . e 15.2. . o 16. . . . . . . . . . . . . . . . . . . . . 13. . . . . Beneficios de la combinaci´n de Bugzilla y MyLyn desde o Eclipse . . . . .2. . . . . . . . . . . . . . . . . . . . . . . . . . 13. . . . . . . . qu´ hay que evitarlo? e . . . . . . . . . . . . . . . . .Patrones de dise˜ o n 16. . . . .2. . . . .1.3. . Ejemplo de implementaci´n . . . .3. . . . . . . Control de hilos . Escribir a una URL .1. .5. . .1. . . . . Creaci´n de hilos en Java . . . . . . . . o 16. . . 209 o 14. . . Leer desde una URL .5. . . . . . . . . . . . . . .2. .2. . . . . . . Principios de POO .1. . . . . . Grupos de patrones de dise˜o . . . . . .5. .3. . .Control de errores con MyLyn y Bugzilla 13. . . .1. Trabajar con Bugzilla . . . . . o n . . .1. . . . . . . . . . . . . . . . . . 15. Cual es el objetivo de MyLyn . . . . . . . . . . . .2. . .3. o 16. . . . . . . .2. . . Sistema de control de tareas MyLyn . . . El patr´n de dise˜o Singleton . .1. Sockets bajo el protocolo UDP 221 222 222 223 223 225 225 225 227 231 232 233 233 233 233 234 234 235 235 236 238 . .5. . . . . . .2. . . . . . . . . . . . . El patr´n de dise˜o Abstract Factory . . . . . . . . . . . . Sistema de gesti´n de errores Bugzilla . . . . .6. . . . . . . . . . Trabajo con Sockets . . . . . 176 o 12. . . . . . . . . . . . .1. Consideraciones sobre el uso de hilos 208 e 14. Sincronizaci´n utilizando el interface Lock . . . . . . 212 14. . . . . o n 16. . . Trabajo con URLs . . . . . . . .Programaci´n para la Red o 15. . . . . Sincronizac´n utilizando los cerrojos intr´ o ınsecos . . . . . . . . . Instalaci´n de Bugzilla . . . . . e 15. . . . 15. . . . 15. . n 16. . . . . . . . . Acceso a Bugzilla desde MyLyn y Eclipse . . . . . . . . . . . . . . .1. . . . . . . . . . . . .3. . . . . . . Cual es el objetivo de Bugzilla . . .1. Ejemplo de implementaci´n . . . . . . . .1.4.5. . . . . . .2. . . . . . . . . . . . . . . . . . .1. . . . . .Programaci´n concurrente con Hilos o 207 14. . . . 13. . . . . .5. . . . . o n 16. . 213 14.3. . . . . ¿Qu´ es un Socket? . . . Convertir una aplicaci´n Swing en un Applet . . . . . . . . . . . . o 13. . . . . . . . Comunicaci´n entre Applets . . . . . . .2. . . . . . . Creaci´n de un Hilo extendiendo a la clase Thread . . . . . o 16. . . . Situaci´n que intenta resolver . . . . . . . . 13. . . . 177 o 13. . .3. .

. .7. . . . o 16. . o 16. . .2. . . . . .xml B. . . . . . . . . . .9. . . . . . . . . . . . . o n 16. . . . . . . .8. .10. . . .1. . . . . . . . . . . . . . . . . . . . . . . . . . . . .1. . . . El patr´n de dise˜o Strategy . . . . .2. . . . . . . . .7. . . .Ejemplo de implementaci´n . . . . . Ejemplo de implementaci´n . . o n 16. Aplicaci´n Hipoteca o C. Situaci´n que intenta resolver o 16. . . . . . . . . . . . . . . . . . . . . . . . E o n 16. . .´ INDICE GENERAL 16. . .10.2. . . . . l patr´n de dise˜o Decorator . . .1. . . . . . . . 7 238 238 244 245 245 247 247 248 249 250 250 255 259 265 . Situaci´n que intenta resolver o 16. . Ejemplo sincronizaci´n o . . .9. . . . . . .2. . Ejemplo de implementaci´n .Situaci´n que intenta resolver o 16. .9. . .8. build. . . . . Ejemplo de implementaci´n .10. . . . . . . o A. . . . . . . . . Situaci´n que intenta resolver o 16. . El patr´n de dise˜o Observer .8. . . o 16. . . . . . . .1. . . . . . . .

8 ´ INDICE GENERAL .

Esto ultimo es s´ ´ ıntoma de que la comunidad alrededor de esta tecnolog´ est´ viva y posee un gran ıa a entusiasmo. o Por otro lado existen excelentes libros. la motivaci´n ha consistido en escribir un libro que se distinguiera del resto de o libros que abordan el aprendizaje del lenguaje de programaci´n Java. Y. c´digo que sea f´cil leer. existen excelentes libros que muestran c´mo programar en Java. al menos. entre ellos. exist´ cabida para escribir un libro que abordase el ıa aprendizaje de Java al mismo tiempo que las herramientas imprescindibles de ayuda al desarrollo. en n´mero inferior. Con un poco m´s de detalle. Pensamos que. y seguimos haci´ndolo. que muestran c´mo u o utilizar herramientas de ayuda y soporte al desarrollo de proyectos en Java. f´cil mantener y que se puede o o a a probar de manera autom´tica. O a aquellos equipos de desarrollo que siguen probando 9 . Para nosotros. hemos impartido.Prefacio La escritura de un libro es una tarea ingente. Esta experiencia nos ha dado la confianza suficiente como para animarnos a escribir el presente libro. que a´n nos queda mucho por aprender. Dentro de nuestra Universidad. La motivaci´n para abordarla debe o ser. Objetivos del libro Dos son los objetivos principales del este libro: Presentar el lenguaje de programaci´n Java. a El segundo de los objetivos es casi una necesidad imperiosa a los equipos de desarrollo que siguen utilizando como herramienta de control de versiones un directorio compartido. la Jaume I. hasta profesionales que quieren mantener al d´ su conocimiento y ıa mejorar sus expectativas laborales. adem´s indicamos unas directrices para o a crear c´digo de calidad. o Presentar algunas de las herramientas de desarrollo que ayudan en el desarrollo de proyectos utilizando Java. tan grande como la tarea que se desea acometer. a pesar del contacto casi diario con Java y sus tecnolog´ reconocemos ıas. alumnos a extranjeros en el Master Europeo Erasmus Mundus sobre tecnolog´ Geoesıas paciales. cursos sobre el lenguaje de programaci´n Java para todo tipo de e o alumnado: desde alumnos de las distintas titulaciones de inform´tica. o Por un lado. en el primer objetivo hemos pretendido no s´lo a o presentar el lenguaje de programaci´n. que el mundo que brinda el aprendizaje u de Java es inmenso y que se renueva constantemente.

En ambos grupos hay cap´ ıtulos que no aparecen en la l´ ınea principal del flujo. Esperamos que esta ordenaci´n haga el tr´nsito suave entre el aprendizaje de Java como o a lenguaje de programaci´n y las herramientas de ayuda al desarrollo. El orden de introducci´n de estas herramientas a sido fuente de largas o conversaciones: ¿Es conveniente introducir al principio la herramienta JUnit siguiendo una orientaci´n hacia el desarrollo guiado por pruebas? ¿Debemos o delegar hasta el segundo bloque de cap´ ıtulos el dedicado a la construcci´n de o proyectos con Ant? Hemos optado por seguir un orden quiz´s m´s conservado y a a menos arriesgado. . En el primero de ellos Java b´sico hemos agrupado los cap´ a ıtulos que consideramos introductorios.10 ´ INDICE GENERAL sus aplicaciones de manera manual. En el segundo grupo Java avanzado aparecen los cap´ ıtulos que consideramos aspectos avanzados del lenguaje con respecto a los cap´ ıtulos del primer grupo. Debe tener un equilibrio entre el espacio dedicado a ella y el reconocimiento a todas las personas. intentando presentar las herramientas en el momento en que conceptualmente se entienda cual es la necesidad que vienen a cubrir. Cada uno de los recuadros representa un cap´ ıtulo. Los conceptos del lenguaje son presentados o desde la base. suponiendo que es la primera vez que el lector se aproxima al lenguaje de programaci´n Java. En primer lugar a nuestro alumnos. Los cap´ ıtulos se han agrupado en dos grandes bloques. e a C´mo est´ organizado este libro o a La Figura 1 muestra la organizaci´n en cap´ o ıtulos del presente libro. o Quien deber´ leer este libro ıa El publico objetivo de este libro son los desarrolladores que quieran aprender el lenguaje de programaci´n Java y ya posean conocimientos de programaci´n o o estructurada y orientaci´n a objetos. Agradecimientos La secci´n de agradecimientos es posiblemente una de las m´s complicadas de o a escribir. Y un largo o etc´tera de pr´cticas desaconsejadas. preferimos ampliar nuestro agradecimiento a colectivos. comentarios y dudas nos han ayudado a darnos cuenta de donde estaban los escollos en la lectura de este libro. Para no dejarnos por citar el nombre de nadie. apreciaciones. Con sus preguntas. por que a fin de cuentas es a ellos a los que va dirigido este libro. y que representan el n´cleo de la programaci´n u o orientada a objetos en Java. que de un modo u otro han contribuido a que un libro tenga su forma final. estos cap´ ıtulos son los que presentan herramientas que consideramos de gran utilidad en el desarrollo de proyectos inform´ticos utilizando tecnolog´ a ıas Java. o Pero este libro tambi´n est´ pensado para aquellas personas que conocen el e a lenguaje de programaci´n Java y a´n no han descubierto la gran cantidad de o u herramientas de ayuda que existen en el desarrollo de proyecto. O para aquellos equipos de desarrollo que utilizan como sistema de seguimiento de errores el correo electr´nico.

´ INDICE GENERAL 11 Figura 1: Organizaci´n del libro. o .

Y finalmente a nuestros amigos por su ´nimo constante para que esta labor a llegase a buen puerto. porque con sus comene n tarios y rectificaciones nos han ayudado a eliminar errores en los contenidos.12 ´ INDICE GENERAL Tambi´n a nuestros compa˜eros de la Universidad. A todos ellos gracias. .

1. . .3. . . . . . A˜adiendo nueva funcionalidad a Eclipse: los plug-ins n 13 14 15 16 16 16 18 21 22 Introducci´n o En este cap´ ıtulo de introducci´n se muestran los or´ o ıgenes del lenguaje de programaci´n Java. . los fundamentos para crear proyectos Java utilizando este Entorno y c´mo se puede enriquecer su funcionalidad mediante la instalaci´n de plug-ins. .3. que naci´ de un proyecto interno o e o en Sun Microsystems en el a˜o 1991 llamado Green project. . . . . .3. . El entorno de desarrollo integrado Eclipse . . . 1.2.3. . .4. . . 1.1. . . Origen del lenguaje de programaci´n Java o El lenguaje de programaci´n Java tiene sus or´ o ıgenes en un lenguaje de programaci´n anterior. . Descarga e instalaci´n de Eclipse . o 1. . . . . . . . Caracter´ ıstica de Java . . . . . . . .3. . . . . .4. 1.1. . . . . . . lenguaje del que hereda gran parte de la sintaxis.1. Origen del lenguaje de programaci´n Java .Cap´ ıtulo 1 Introducci´n o Contenidos 1. . . . . En la segunda parte del cap´ ıtulo se presenta en Entorno de Desarrollo Integrado Eclipse. . o 1. . . . . . . Principales caracter´ ısticas del entorno de desarrollo Eclipse . Configurando el aspecto de Eclipse: Perspectivas y Vistas . n Oak fue creado con el objetivo de ser el lenguaje de programaci´n con el o que programar dispositivos electr´nicos dom´sticos. . . .2. . . Herramientas de desarrollo . . . . . . . . . . . 1. . .1. . . . . . Oak ten´ entre otras. . . . . . en particular aparatos de o e televisi´n inteligentes e interactivos. . llamado Oak (roble en ingl´s).4. . . . . . . El primer ejemplo . . . . . 1. . sus principales caracter´ o ısticas y las diferencias con respecto a C++. las siguientes caraco ıa. . . . . . . . . . . o o 1. . ter´ ısticas de inter´s: e 13 .3. . .

Las nuevas caracter´ ısticas generales que se a˜adieron son: n Seguridad. podremos a ejecutar el mismo programa escrito en Java sin necesidad de volverlo a compilar. llamado bytecode. traducir´ los a a bytecodes a c´digo nativo para esta plataforma. se genera un c´digo o o intermedio. una m´quina virtual para una plataforma Windows 7 de 64 bits. En el proceso de compilaci´n de un programa en Java. ya no se ten´ la restricci´n de la ejecuci´n en dispositivos de ıa o o electr´nica de consumo. Potencia. El uso de la m´quina virtual garantiza la independencia de la plataforma en a Java. De o o modo simult´neo. As´ a ı. Independiente del hardware. ya que los programas que se ejecutan en un navegador se descargan desde Internet. Adem´s. la ventaja de que un programa escrito en Java se puede a ejecutar en una gran cantidad de plataformas ha hecho de ´l un interesante e lenguaje de programaci´n por su ((universalidad)). Puede parecer que este paso de traducir los bytecodes a c´digo nativo de la o plataforma suponga una p´rdida de rendimiento en la ejecuci´n de los programas e o en Java. y otra m´quina virtual para una o a plataforma Linux de 64 bits traducir´ los mismos bytecodes a c´digo nativo para a o esta otra plataforma. Y del lenguaje de programaci´n C++ toma su a o sintaxis. Si disponemos de una m´quina virtual para nuestra plataforma. Caracter´ ıstica de Java Java es un lenguaje de programaci´n orientado a objetos y de prop´sito geneo o ral que toma de otros lenguajes de programaci´n algunas ideas fundamentales. INTRODUCCION Orientado a objetos y de prop´sito general. la aparici´n de los primeros navegadores web. El proyecto de televisi´n inteligente e interactiva nunca se materializ´. Y este fue o el inicio de Java. o en particular toma de Smalltalk el hecho de que los programas Java se ejecutan sobre una m´quina virtual .14 ´ CAP´ ITULO 1. que la m´quina virtual interpreta y traduce a a llamadas nativas del sistema sobre el que se ejecuta la m´quina virtual. pero esto no es as´ gracias a la introducci´n de la tecnolog´ JIT (Just ı o ıa . o Java se ha consolidado como lenguaje de programaci´n gracias a que su o curva de aprendizaje es relativamente suave para programadores provenientes de C++. Sintaxis parecida a C++. las m´quinas a virtuales sobre las que se ejecutan son nativas de la plataforma correspondiente. a principios de la d´cada de los 90 surgi´ Internet y con a e o ella. o Robusto. Los bytecodes son los mismos en ambos casos. as´ llamado porque cuando se intent´ registrar el nombre Oak ı o este ya estaba registrado.2. o 1. Los l´ o ıderes del Green project fueron conscientes de la importancia que iba a tener Internet y orientaron su lenguaje de programaci´n Oak para que programas escritos en este lenguaje de o programaci´n se pudiesen ejecutar dentro del navegador web Mozilla.

o • No existen punteros. o Conexi´n con sistema de seguimiento de errores. Herramientas de b´squeda. Algunas caracter´ ısticas comunes a los IDE son: Coloreado de la sintaxis. EL ENTORNO DE DESARROLLO INTEGRADO ECLIPSE 15 In Time compilation). de tal modo que la siguiente vez que se llama o al mismo m´todo no es necesaria su interpretaci´n ya que el c´digo nativo para e o o ese m´todo se almacen´ previamente. o Herramientas de depuraci´n de c´digo. este se interpreta generando c´digo nativo de la e o plataforma sobre la que se ejecuta la m´quina virtual. La o o comodidad reside en que los entornos de desarrollo integrados son mucho m´s a que un simple editor de textos. o Los tipos de datos est´n estandarizados. La idea b´sica de esta tecnolog´ es que la primera vez a ıa que se llama a un m´todo. se almacena. a o . • Recolector de basura.3. o o Junto a estas caracter´ ısticas.1. pero una vez generado a este c´digo nativo. u Asistentes para la escritura de c´digo. o • Gesti´n de excepciones. e o Otras caracter´ ısticas generales de Java son: Seguridad desde el punto de vista del programador: • Comprobaci´n estricta de tipos. o Ejecuci´n de aplicaciones sin abandonar el entorno. los modernos IDE poseen algunas otras realmente espectaculares como por ejemplo: Conexi´n con sistemas de control de versiones. Seguridad desde el punto de vista del usuario de aplicaciones: • Los programas se ejecutan sobre una m´quina virtual. Soporta programaci´n concurrente de modo nativo. El entorno de desarrollo integrado Eclipse Un entorno integrado de desarrollo o IDE de sus siglas en ingl´s (emphIntegrated e Develop Environment) nos permite escribir c´digo de un modo c´modo. o 1. o Herramientas avanzadas para el an´lisis de c´digo. a S´lo se admite herencia simple. a • Espacio de nombre.3. o Facilidades para la creaci´n de tareas.

1. Descarga e instalaci´n de Eclipse o Eclipse se puede descargar desde el sitio web http://www. Una vez deso cargado el fichero comprimido. a Conexi´n a gestores de bases de datos. o Eclipse es un IDE orientado al desarrollo de proyectos con tecnolog´ Java.16 ´ CAP´ ITULO 1.3. o e El aspecto de las perspectivas se puede configurar. si haces click sobre una de estas solapas sin soltar el bot´n del rat´n. mantenido por la Eclipse Foundation. Una Perspectiva es un contenedor de Vistas. La pantalla de inicio se puede cerrar pulsando el o aspa que se encuentra a la derecha de la leyenda Welcome. Los iconos que muestra esta pantalla son enlaces a sitios de informaci´n sobre Eclipse. La vista o o Problems muestra un listado con los errores y avisos presentes en el c´digo de o nuestro proyecto. por ejemplo la vista Package Explorer donde se muestra informaci´n de la configuraci´n de nuestros proyectos.org. son componentes visual que pueden mostrar desde un editor de c´digo. Configurando el aspecto de Eclipse: Perspectivas y Vistas El interface gr´fico de usuario de Eclipse cuenta con dos conceptos fundamena tales: las Perspectivas y las Vistas. e o u . La Figura 1. u Existe una gran cantidad de vistas.2. 1. puedes acceder a cualquiera de ellas a trav´s de la opci´n Show view del men´ Window.eclipse. Te habr´s dado cuenta a que cada una de estas vistas est´ etiquetada con un nombre dentro de una a solapa. Esto o te permite organizar las vistas dentro de las perspectivas seg´n tus preferencias. o o puedes trasladar la vista a cualquier otra posici´n dentro de la perspectiva.1. Cada una de estas vistas est´ orientada a presentar un tipo a de informaci´n de nuestro proyecto o tareas relacionadas con ´l.1 muestra la p´gina a de inicio de Eclipse.2 o a ıa se muestra el aspecto de Eclipse al mostrar la Perspectiva por defecto orientada al desarrollo de aplicaciones Java. hasta un ´rbol de jerarqu´ de clases en Java. ıa aunque no es el unico lenguaje de programaci´n al que da soporte. Principales caracter´ ısticas del entorno de desarrollo Eclipse Eclipse re´ne todas las caracter´ u ısticas comunes a los modernos IDE enumeradas m´s arriba. Eclipse es ´ o una herramienta de software libre. Esta perspectiva contiene varias vistas. En una misma Perspectiva podemos agrupar m´s de una Vista. Existen versiones para las principales plataformas y sistemas operativos. mediante un plug-in nos podemos conectar al sistema de control de versiones Subversion 1. INTRODUCCION Herramientas de an´lisis de rendimiento. a Las Vistas por su lado. lo unico que debemos hacer para empezar a ´ utilizarlo es descomprimirlo en alg´n directorio y seguidamente ejecutar el biu nario correspondiente a nuestra plataforma.3.3. Por ejemplo. En la figura 1. Una particularidad de Eclipse es que no necesita instalaci´n. Adem´s posee un sistema de plug-ins con los que se pueden a˜adir a a n nuevas funcionalidades.3.

. EL ENTORNO DE DESARROLLO INTEGRADO ECLIPSE 17 Figura 1.1: Pantalla inicial de Eclipse Figura 1.3.1.2: Perspectiva inicial orientada al desarrollo de proyectos Java2 SE.

se abrir´ una ventana como la a a mostrada en la Figura 1.3. m´s r´pido. o Figura 1.3: Ventana para la creaci´n de un proyecto Java utilizando Eclipse.4 El siguiente paso que vamos a dar es crear una nueva clase en nuestro proyecto. el resultado se muestra en la Figura 1. INTRODUCCION Figura 1. Esta clase va a ser muy sencilla. Otro procedimiento. El primer ejemplo Vamos a crear un primer proyecto Java con Eclipse. En la vista Package Explorer aparecer´ el nombre del nuevo proyecto a reci´n creado. En esta ventana lo unico que vamos a introducir es ´ el nombre del proyecto. de crear una nueva clase en Eclipse es pulsar directamente a a . y unicamente nos va a servir para conocer ´ cual es el procedimiento de creaci´n. haz click con el bot´n derecho del rat´n o o sobre el nombre del proyecto reci´n creado. y sobre el men´ emero u gente que aparecer´ selecciona New → Project. 1. Una vez introducido el nombre del proyecto. La vista de proyecto sigue una estructura de ´rbol. compilaci´n y ejecuci´n utilizando o o o o Eclipse. y ver´s que ese mismo icono la encuentras en la barrar o a de herramientas en la parte superior de la ventana de Eclipse. pulsa el bot´n Finish. se abrir´ un men´ emergente. simplemente haz click con el bot´n derecho en la vista Package Explorer.18 ´ CAP´ ITULO 1. Para ello. ver´s o a que el aspecto de Eclipse se actualiza para mostrar el nuevo proyecto reci´n e creado.3. presta atenci´n al icono que se dibuja a la o o izquierda de esta opci´n.4.4: Estructura m´ ınima de un proyecto en Eclipse. see a u lecciona la opci´n New → Class. Para crear una nueva clase. que puedes e a desplegar. edici´n.

se ha abierto una nueva vista del editor e a de c´digo tal y como muestra la Figura 1.6. El siguiente paso va a ser ejecutar el programa.5. EL ENTORNO DE DESARROLLO INTEGRADO ECLIPSE 19 Figura 1. en el Cap´ ıtulo 2 conoceremos algunas de estas convenciones de codificaci´n Java. o ese icono en la barra de herramientas. Una vez escrita la nueva l´ ınea de c´digo graba el fichero.1. Selecciona la opci´n public static void main(String[] args) o Esta tres piezas de informaci´n aparecen en la Figura 1. Esta instrucci´n sirve para mostrar o una cadena de texto por consola.5: Creaci´n de una nueva clase Java en Eclipse. se abrir´ la nueva ventana mostrada en la Figura o a 1. o para ello haz click con el bot´n derecho del rat´n sobre el editor de c´digo o o o y en el men´ emergente que aparecer´ selecciona la opci´n Run As → Java u a o Application.5. bajo el nodo del ´rbol src un nuevo nodo con nombre hola y bajo a ´l el nodo HolaMundo. Adem´s.7. . ahora podr´s ver que a a se ha creado. o o Ver´s que de nuevo se actualiza la estructura del proyecto. para ello pulsa la o combinaci´n de teclas Ctrl + S. En esta ventana vamos a introducir tres piezas de informaci´n: o Un nombre de paquete en min´sculas (en el Cap´ u ıtulo 3 conocer´s con a detalle el significado de los paquetes en Java.java.3. Al seleccionar esta opci´n. Un nombre de clase con la primera letra de cada palabra en may´sculas u y sin espacios entre ellas. Finalmente pulsa el bot´n Finish. Recuerda introo ducir el nombre del paquete y de la clase utilizando may´sculas y min´sculas u u tal y como se muestra en la Figura 1. o Hagamos una peque˜a modificaci´n sobre este c´digo. A˜ade la siguiente n o o n l´ ınea tal y como se muestra en la Figura 1.5.

o Figura 1.6: Aspecto del editor de c´digo Java.20 ´ CAP´ ITULO 1. . INTRODUCCION Figura 1.7: El primer programa en Java Hola mundo.

1. HERRAMIENTAS DE DESARROLLO 21 Figura 1. cada vez que haces modificaciones en el c´digo de definici´n o o de una clase y grabas el fichero. o a e En el estado actual de madurez de las tecnolog´ de desarrollo de proyectos ıas inform´ticos. las herramientas de o despliegue de la aplicaci´n. El trabajo con Eclipse es realmente sencillo. E incluso. La r´pida evoluci´n de la tecnolog´ inform´tica permite vaticinar a o ıa a que seguir´n apareciendo cada vez m´s y mejores alternativas.4. pero como lector no debes seguir ciegamente nuestra elecci´n. tal a o y como muestra la Figura 1. o JUnit Es un framework de pruebas autom´ticas de c´digo. 1. Mejor a´n. o En la vista Console podr´s ver el resultado de la ejecuci´n del programa. nos han parecido las m´s e a adecuadas a nuestro caso. contamos con excelentes herramientas de software libre que cubren este tipo de tareas. Todas ellas a . a a En particular vamos a presentar las siguientes herramientas: Subvesion Es una herramienta para la gesti´n de versiones. a o Ant Es una herramienta de construcci´n de proyectos. Eclipse compila autom´ticamente el c´digo a o modificado. t´mala como punto de partida que le permita evaluar otras o u o alternativas. y un largo etc´tera. a trav´s de nuestra propia experiencia. en algunos casos.4. o Bugzilla Es una herramienta de gesti´n y seguimiento de errores. En este libro vamos a presentar algunas de estar herramientas.8 Por defecto. la gesti´n y seguimiento de errores. Herramientas de desarrollo Cuando nos planteamos desarrollar un proyecto inform´tico ser´ de gran ayuda a a elegir una serie de herramientas que nos faciliten actividades tales como el control de versiones de nuestro c´digo o la prueba autom´tica de nuestros m´todos. De este modo la compilaci´n se realiza de modo transparente a o medida que vamos trabajando en nuestro proyecto. y una unica clase en la que hemos introducido una l´ ´ ınea de c´digo que muestra o un mensaje de texto por consola.8: Resultado de le ejecuci´n del primer programa en Java Hola mundo. resulta impensable iniciar el desarrollo de un proyecto sin planificar a el control de versiones. en la actualidad. existe m´s de una soluci´n de software libre. Las hemos elegido porque. o Cada una de las anteriores herramientas cuentan con una gran popularidad dentro de la comunidad de desarrollo de proyectos inform´ticos. con lo que podemos evaluar varias a o de ellas y seleccionar la que mejor se adapte a nuestra forma de trabajar antes de empezar a utilizar. o e Afortunadamente. Con estos sencillos pasos hemos creado nuestro primer proyecto en Java. o MyLyn Es una herramienta de gesti´n de tareas.

Una referencia completa sobre el entorno de desarrollo Eclipse se puede encontrar en la p´gina web http://www. el control de versiones de nuestro c´digo sin necesidad de abandonar Eclipse.org.22 ´ CAP´ ITULO 1. o 1. o Eclipse cuenta con un sistema de plug-ins de tal modo que podemos aumentar sus ya de por s´ numerosas y potentes funcionalidades con otras nuevas.1. ı As´ por ejemplo. desde Eclipse se puede interaccionar con todas las herramientas expuestas en la secci´n anterior. a . En o el Cap´ ıtulo 4 se mostrar´ c´mo instalar el plug-in para Eclipse y c´mo trabajar a o o con ´l.4. podemos instalar un plug-in de Eclipse para poder realizar ı. A˜ adiendo nueva funcionalidad a Eclipse: los plugn ins Afortunadamente. Todas ellas se pueden utilizar en proyectos que utilicen un lenguaje de programaci´n alternativo a Java. e Lecturas recomendadas Un escueto resumen sobre lo que significa el lenguaje de programaci´n o Java se puede encontrar en [11]. o existen o versiones de ellas para otros lenguajes de programaci´n.eclipse. INTRODUCCION cuentan con otras excelentes alternativas.

2. .3. . Definici´n de una clase . .2. . . . . .3. . . . . . . . . .2. Estructuras de control de repetici´n.1. Arrays de datos en Java. El bucle for . . . . . . . . . 2. . . . . . . . . . . . . . . . .4. . . . . . 2. . . . .2. . . 2. . Atributos de una clase . . . .2. . . .4. El bucle do. . . . . . . . ..else. no es lo mismo a abstraer la entidad del mundo real ((Persona)) para utilizarla en una aplicaci´n o 23 . . . ..4. . . . . Comentarios. El bucle while .1. . .6. 2.1. . . . o 2.2. . e 2. . .1. . . .2.4. . . . . o 2. .1. . .1. . . . . . . o 2. . . . . . . . o 2. .while .2. . . . . . . . . . . .3. . . . . . . . . . . A estos ejemplares en o POO se les llama objetos o instancias de la clase.4. . . . . . . . . .Cap´ ıtulo 2 Clases en Java Contenidos 2. .1.2. . .7. . . . . El recolector de basura. 2. .1. . M´todos de una clase. Las clases son abstracciones de entidades de la realidad que sirven como plantillas para la creaci´n de ejemplares de la clase. . . 2. . . 2. . . . . e 2. . . . . . . Estructuras de control de selecci´n. Finalizaci´n. .2.4. . . . . . . Miembros de una clase . Modificadores de acceso. . .. . 2. . o 24 25 25 26 28 32 33 34 36 37 37 38 38 39 39 39 40 42 43 44 45 Introducci´n o Las clases son la piedra angular de los lenguaje de programaci´n orientados a obo jetos (POO).4. . . . . . es decir. . . .9. . . . .. . . 2. Comentarios de documentaci´n. . . . . . . . Sobrecarga de m´todos y constructores . . M´ltiples caminos con la sentencia switch u 2. . . Modificadores static y final. .4. 2. Tipos de datos en Java. . . . . . . . . . . . El proceso de abstracci´n deo pende del contexto en el que se utilizar´n los ejemplares. . . . . . . . . . . . . . . . . . . . . . . . . Bifurcaciones con la sentencia if. . . . .5. . . Estructuras de control. . . . . . . . .1. . . .2.8. . . Constructores. . . . . . . . . . . . . .3. . . 2. 2.4. .2. . . . .

En POO la o reutilizaci´n implica escribir una nueva clase sin partir de cero. Dicho de otro modo cada uno de los contactos de la agenda est´ creado a partir de la misma plantilla a Persona. que es la abstracci´n de una persona del mundo real en el contexto de o la aplicaci´n de la agenda telef´nica. En general. pero no es probable que cambie de apellidos). Finalmente avanzaremos la idea de reutilizaci´n de una clase. a partir de una abstracci´n. Al conjunto de operaciones que define una clase se le llama m´todos de la clase. e Cuando hablamos de miembros de una clase hacemos referencia tanto a los atributos como a los m´todos de la clase. El conjunto de todos los valores de un objeto va a u e determinar su estado en un momento concreto. del siguiente modo . Definici´n o Al conjunto de valores definidos en la clase se le llama atributos de la clase. todo en a Java es un objeto. sino tomano do como base otra clase cuyo comportamiento ampliamos o modificamos. En este cap´ ıtulo vamos a ver c´mo. podemos o o transcribirla a c´digo Java para crear una clase. las caracter´ ısticas de la entidad real que nos interese utilizar en la aplicaci´n y las operaciones que podamos realizar sobre o estas abstracciones ser´n diferentes. Definici´n de una clase o Supongamos que queremos programar una aplicaci´n de agenda telef´nica. como el nombre y los apellidos del contacto y su n´mero de tel´fono. a Java es un lenguaje de programaci´n orientado a objetos. o o ¿Qu´ necesitamos especificar para crear un objeto o ejemplar de la clase e Persona? Cada uno de los objetos creados a partir de esta clase contendr´ una a serie de valores que lo identifican. como por ejemplo consultar su nombre. El o o objetivo de nuestra agenda telef´nica es gestionar una serie de contactos.1. Los detalles de c´mo ampliar o extender el comportamiento de una clase base se o introducir´n en el Cap´ a ıtulo 3. Volviendo al ejemplo de la agenda telef´nica. Cada o uno de estos contactos representa a una Persona. y c´mo a partir de una clase o o podemos crear instancias de esa clase. y o el conjunto de atributos y m´todos de la clase se define en un bloque delimitado e por llaves. y me va a ofrecer una e serie de operaciones que puedo realizar sobre ella. sobre cada uno de los objetos vamos a poder llevar a cabo un conjunto de operaciones definidas en la clase. 2. que pueden o no variar e a lo largo del tiempo (un contacto de mi agenda puede cambiar de n´mero de u tel´fono. cada una de las ((Persona)) o de la agenda va a tener una serie de datos de inter´s.24 CAP´ ITULO 2. Por otro lado. CLASES de gesti´n de los clientes de una cl´ o ınica. que para utilizarla en una aplicaci´n o de seguros o de banca. e La definici´n de una clase en Java empieza con la palabra reservada class. De hecho en Java existen dos grandes tipos de datos: tipos de datos primitivos y tipos de datos referencia. y aunque como o veremos posee tipos b´sicos para poder manejar enteros o caracteres.

2. →Tel´fono. en el caso del Telefono podemos optar entre representarlo como un n´mero entero o una cadena de caracteres. cada contacto de mi agenda tiene. un n´mero de u tel´fono.. Representemos gr´ficamente lo que tenemos hasta ahora a   Persona posee: →Nombre.2. al menos.1. en el caso del Nombre. al escribir el nombre de la clase hemos empezado la palabra por una letra may´scula. String telefono .2. por ejemplo. o datos. →Apellidos. el nombre y los apellidos de cada uno o de los contactos. parece evidente que. y que al empezar el nombre de un atributo lo hemos u empezado por min´scula. Miembros de una clase Atributos de una clase Ahora que ya sabemos que debemos abstraer una ((Persona)) del mundo real en el contexto de nuestra aplicaci´n la siguiente pregunta es: ¿Cuales son las o caracter´ ısticas. Veremos m´s reglas de convenci´n en la Secci´n 2. Los atributos los declararemos de este modo: 1 2 3 4 5 6 c l a s s Persona { S t r i n g nombre . MIEMBROS DE UNA CLASE 25 1 2 3 4 c l a s s Persona { // D e c l a r a c i ´ n de a t r i b u t o s o // D e f i n i c i ´ n de m´ todos o e } 2. de una persona relevantes en el contexto de una agenda telef´nica? Sin duda uno de estos datos es el n´mero de tel´fono de la persoo u e na. . ¿Qu´ otros datos pueden ser de inter´s almacenar en una agenda tee e e lef´nica?. de manera simplificada. String apellidos .2. utilizaremos una cadena de caracteres. si queremos almacenar los u n´meros de tel´fono en formato internacional (Ej: (+34) 555 555 555) optaremos u e por representarlos como cadenas de caracteres. Esta es una convenci´n de codificaci´n en Java que u o o conviene seguir puesto que est´ ampliamente extendida entre los desarrolladores a Java. 2.9. F´ a o o ıjate tambi´n que e hemos definido cada atributo en un l´ ınea distinta y que cada l´ ınea acaba con el caracter . // D e f i n i c i ´ n de m´ todos o e } F´ ıjate que. e   ¿C´mo se definen estos atributos en la clase? De cada uno de los atributos o debemos especificar su tipo.

e Una vez hemos creado una instancia de la clase Persona. } Sintaxis La sintaxis de declaraci´n de un m´todo es: o e {modificadores} tipoRetorno nombre(tipo argumento1. Por ejemplo: numeroTelefono. . ve´moslas: o a 1.5 el acceso directo a los atributos de una clase est´ desaconsejado.) { Bloque de definici´n del m´todo. e e Si est´s familiarizado con las matem´ticas. este ser´ el tipo del valor retorno. ¿C´mo podemos recuperar el nombre que o almacenamos en un contacto de nuestra agenda?. Un m´todo que cumple este objetivo es e el siguiente: 1 2 3 String getPersona () { return nombre . la segunda y siguiena a tes palabras que constituyen el nombre se escriben con su primera letra en may´scula.. u Veamos ahora c´mo definir las operaciones que podremos realizar sobre las o instancias de la clase Persona. Un m´todo tiene un nombre que lo identifica. tipo argumento2. Una posibilidad es simplemente leer el valor del atributo. Dentro de los par´ntesis se define la lista de argumentos del m´todo. a 3. e . por ejemplo seno(45o ) significa que queremos utilizar el c´lculo del a seno sobre el argumento 45 grados. o a La respuesta es: a trav´s de una llamada a un m´todo que devuelva el nombre e e del contacto.2. e 2. el tipo de dato de o retorno es una cadena class String. en este caso getNombre. o e } En estas pocas l´ ıneas de c´digo hay varias novedades. Detr´s del nombre del m´todo aparecen unos par´ntesis sin nada en su ina e e terior. ¿C´mo podemos reo cuperar a partir de ella su nombre?. Delante del nombre del m´todo escribimos el tipo del valor de retorno. e u Si estos nombres est´n formados por m´s de una palabra. 2. CLASES Seg´n las reglas de convenci´n m´s extendidas en Java. En el caso de la recuperaci´n del nombre. M´todos de una clase. pero como veremos en la secci´n 2.. que indica que no necesito especificar ning´n argumento para poder hacer u uso del m´todo. los argumentos de los m´todos a a e tienen el mismo significado que los argumentos de las funciones matem´tia cas. u o a el nombre de la clase se debe escribir con la primera letra en may´scula y los u nombres de los atributos y m´todos deben empezar por una letra en min´scula.2. En nuestro caso la lista est´ vac´ lo a ıa. en e nuestro caso. al definir una clase. como lo que el m´todo devuelve es el nombre cuyo tipo es e un String.26 Reglas de convenci´n o CAP´ ITULO 2.

es sencillo escribir dos nuevos m´todo que dee vuelvan los apellidos y el n´mero de tel´fono de una Persona. hay que a ıa. } String getTelefono () { return t e l e f o n o . hemos seguido una convenci´n de codificaci´n: o o Regla de convenci´n o Los m´todos que modifican el valor de los atributos de una clase se nombran e empezando con la palabra inglesa set seguida por el nombre del atributo. u . MIEMBROS DE UNA CLASE 4.2. e e De nuevo. si un m´todo devuelve el valor de un atributo o o e empieza por la palabra inglesa get.2: M´todo para modificar el valor del tel´fono. 27 Como ves. Por ejemplo. f´ ıjate que si un m´todo no recibe argumentos su lista de argue mentos est´ vac´ Pero si un m´todo no devuelve ning´n par´metro. un contacto de mi agenda podr´ cambiar de n´mero de tel´fono. luego parece buena idea que la clase ıa u e Persona me proporcione un m´todo que permita modificar el valor del atributo e telefono. ı Con lo que ya hemos visto. Y una o nueva convenci´n de codificaci´n. } } Listado 2. Para devolver un valor utilizamos la palabra reservada return. String apellidos . Aqu´ tienes el u e ı c´digo de la clase: o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 c l a s s Persona { S t r i n g nombre . La definici´n del m´todo va dentro de las llaves . } String getApellidos () { return a p e l l i d o s . de ah´ que hayamos escrito getNombre(). el siguiente m´todo no devuelve ning´n valor: e u 1 2 3 void nada ( ) { // C´ digo d e l m´ todo o e } En muchas ocasiones resulta interesante poder modificar el valor de los atributos.1: C´digo de la clase Persona o De nuevo.2. e u a indicarlo expl´ ıcitamente utilizando la palabra reservada void. String telefono . como el que se muestra en el siguiente ejemplo: 1 2 3 void s e t T e l e f o n o ( S t r i n g n u e v o T e l e f o n o ) { t e l e f o n o = nuevoTelefono . String getPersona () { return nombre . Como ya hemos comentado anteriormente. cuya primera letra se escribe en may´sculas. } Listado 2. muchos conceptos nuevos en tan s´lo tres l´ o ıneas de c´digo. o e 5.

. this . ¿C´mo resolvemos la ambig¨edad entre el nombre o u del atributo y el nombre del argumento?. 3. Veremos con m´s detalle el significado de la palabra reservada e a this en la secci´n 2. F´ ıjate que los nombres de los tres argumentos coinciden con los nombres de los atributos. tres de tipo String.2. Para crear un ejemplar de una clase utilizamos m´todos especiales llamados e constructores de la clase. } void s e t A p e l l i d o s ( S t r i n g n u e v o s A p e l l i d o s ) { apellidos = nuevosApellidos .28 CAP´ ITULO 2.4: Constructor con par´metros de la clase Persona a Volvemos a tener nuevos conceptos en estas l´ ıneas de c´digo.3. o 4. tiene un lista de argumentos que en este e caso no est´ vac´ si no que indica que va a recibir tres argumentos y los a ıa.3. CLASES De modo an´logo. estamos haciendo referencia al argumento del o m´todo. } Listado 2. la clase tiene declarado un atributo de tipo String llamado nombre y el primer argumento del constructor tambi´n se llama nombre e y es de tipo String. En las siguientes l´ ıneas de c´digo se muestra c´mo se o o define un constructor de la clase Persona: 1 2 3 4 5 P e r s o n a ( S t r i n g nombre . si s´lo escribimos nombre. 2. utilizando la palabra reservada this. Constructores. para ello necesitamos escribir m´todos especiales que nos sirvan para crear instancias de e la clase. si escribimos this. t h i s . tal y como se muestra a continuaci´n: o 1 2 3 4 5 6 7 void setNombre ( S t r i n g nuevoNombre ) { nombre = nuevoNombre .nombre estamos haciendo referencia al atributo. this . ya que estos m´todos u e especiales nos sirven para crear objetos. } String telefono ) { Listado 2. e 2. ve´moslo: o a 1. a estos m´todos especiales se les llama constructores de la clase. a p e l l i d o s = a p e l l i d o s . e en nuestro caso el nombre del m´todo es Persona que es precisamente el e nombre de la clase. S t r i n g a p e l l i d o s . Como cualquier otro m´todo. Un constructor no devuelve ning´n valor de retorno. t e l e f o n o = t e l e f o n o . nombre = nombre . Un constructor es un m´todo cuyo nombre coincide con el de la clase. Ahora queremos crear ejemplares de esta clase. podemos a˜adir a la clase Persona dos nuevos m´todos a n e para poder modificar el valor de los atributos nombre y apellidos.3: M´todos para modificar el nombre y los apellidos de una Persona e Ya tenemos escritos m´todos que nos permiten leer y modificar los atributos e de la clase Persona.

Veamos todo el c´digo que hemos escrito para la clase Persona: o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package agenda .2.5: Una clase sin ning´n constructor.2. De momento qu´date con la idea de que es importante que tus clases definan el constructor e por defecto. public c l a s s P e r s o n a { S t r i n g nombre . } } Listado 2. todas tus clases deber´ definirlo. } String getTelefono () { return t e l e f o n o . 2. t e l e f o n o = t e l e f o n o . Si tu clase no proıan porciona ning´n constructor. i n t getA ( ) { return a . MIEMBROS DE UNA CLASE Escribamos otro constructor para la clase Persona: 1 29 Persona ( ) { } M´s novedades conceptuales en estas l´ a ıneas de c´digo: o 1. Persona ( ) { } P e r s o n a ( S t r i n g nombre . El compilador de Java crear´ el u a constructor por defecto por nosotros. a p e l l i d o s = a p e l l i d o s . adem´s hemos modificado la definici´n de los m´todos set para a o e . de hecho. como en el caso del Listado 2. } String getApellidos () { return a p e l l i d o s . de modo que puedas crear instancias a partir de ella. 1 2 3 4 5 6 7 class SinConstructores { private i n t a . } S t r i n g getNombre ( ) { return nombre . } } String telefono ) { Listado 2. S t r i n g a p e l l i d o s . String apellidos . La lista de argumentos de este constructor est´ vac´ a ıa. String telefono .6 hemos agrupado los m´todos get/set para cada uno de e los atributos.5. No hemos escrito ninguna l´ ınea de c´digo entre las llaves. el compilador de u Java crea el constructor por defecto para la clase. this . nombre = nombre . t h i s .6: C´digo de la clase Persona o En el Listado 2. this . o A este constructor tan particular se le llama Constructor por defecto y hablaremos m´s sobre ´l en el cap´ a e ıtulo 3 dedicado a la herencia en Java.

por ejemplo. p r i n t l n ( " N o m b r e : " + unaPersona . System . O System .7. el c´digo de e o tu proyecto. t e l e f o n o ) . System .6. System . Eclipse organiza los proyectos en carpetas. Escribe a a e el resto de c´digo que aparece en el Listado 2. para ello crea en el proyecto una nueva clase y ll´mala PruebaPersona a y como nombre de paquete introduce agenda. CLASES deshacer la ambig¨edad entre el nombre de los atributos y de los argumentos. ´ } } . introduce uno a adecuado (por ejemplo ((AgendaTelefonica))). Hay varias o opciones para crear un nuevo proyecto en Eclipse. o u t . escribamos nuestra primera peque˜a aplicaci´n en n o Java para probar todo lo que hemos visto hasta ahora. g e t A p e l l i d o s ( ) ) . o u t . Es muy recomendable que cada a clase est´ dentro de un paquete (veremos con m´s detalle el significado de los e a paquetes en Java en la Secci´n 3. " 1 2 3 4 " ) ." ) . o bien puedes pulsar el bot´n de creaci´n o o de proyectos. o u t . p r i n t l n ( " M u e s t r a i n f o r m a c i ´ n a c c e d i e n d o d i r e c t a m e n t e a l o s o campos . donde se muestra a la vista Package Explorer te aparece una carpeta con el mismo nombre que el proyecto reci´n creado. a trav´s del men´ puedes e u elegir File → New → Java Project. o bien pulsando directamente el bot´n de creaci´n de una o o nueva clase. g e t T e l e f o n o ( ) ) . System . Se abrir´ una ventana de di´logo solicit´ndote un nombre para a a a la nueva clase y el paquete donde se incluir´. a p e l l i d o s ) . y en el cuadro de di´logo de creaa ci´n de la clase marca la casilla public static void main(String[] args).30 CAP´ ITULO 2. o u t . public c l a s s PruebaPersona { /∗ ∗ ∗ @param a r g s ∗/ public s t a t i c void main ( S t r i n g [ ] a r g s ) { // TODO Auto−g e n e r a t e d method s t u b P e r s o n a unaPersona = new P e r s o n a ( " ´ s c a r " . u tal y como hemos hecho en el caso del constructor con argumentos. o u t . o u t . u Lo siguiente que vamos a hacer es escribir una clase para probar nuestra clase Persona. ´ System . y ya puedes pulsar directamente la tecla Finish. p r i n t l n ( " N o m b r e : " + unaPersona . " B e l m o n t e " . Seg´n las convenciones de Java. Ver´s que se abre la a vista del editor de c´digo en Eclipse y que si despliegas la carpeta de proyecto o te aparece el fichero de clase Persona. o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package agenda .6).java. o u t . y para el nombre de la clase Persona. System . Escribe la definici´n de la clase o seg´n el Listado 2. Vamos a utilizar para ello el entorno integrado de desarrollo Eclipse. Antes de pasar adelante. p r i n t l n ( " T e l e f o n o : " + unaPersona . o u t . los nombres o u de paquetes se escriben en min´scula. System . Eclipse te solicitar´ un nombre para el proyecto. p r i n t l n ( " A p e l l i d o s : " + unaPersona . para el nombre del u paquete agenda." ) . p r i n t l n ( " M u e s t r a i n f o r m a c i ´ n l l a m a n d o a l o s m ´ t o d o s d e l a o e clase . p r i n t l n ( " A p e l l i d o s : " + unaPersona . o con ello Eclipse crear´ de manera autom´tica el m´todo principal main. Para crear un nueva clase en Eclipse puedes hacerlo a trav´s del men´ File e u → New → Class. p r i n t l n ( " T e l e f o n o : " + unaPersona . Escribe. ficheros de bibliotecas y recursos necesarios estar´n en la carpeta a del proyecto. Ver´s que en la columna izquierda de Eclipse. inicia pues esta aplicaci´n. nombre ) . getNombre ( ) ) .

a o . En las siguientes secciones veremos o el significado de todos los modificadores que tiene este m´todo delante de su e nombre que es main. Ejecutemos este primer programa para ver cual es el resultado. este m´todo es el punto de e entrada a la ejecuci´n de un programa Java.out. para poder usar la instancia a la Persona reci´n creada e utilizaremos la variable de referencia unaPersona. Reglas de convenci´n o Los nombre de los paquetes y subpaquetes se escriben en min´sculas. Esta clase tiene un unico m´toa ´ e do public static void main(String[] args). esto indica que nos guardamos lo que el operador new devuelve en la variable de tipo referencia a Persona que llamamos unaPersona.println("Texto"). el trabajo de edici´n en Eclipse es realmente sencillo o y te ir´s dando cuenta que este entorno de programaci´n Java es muy potente. de a e momento la idea es que. En la l´ ınea n´mero 10.2. "1234"). o Nombre: ´scar O Apellidos:Belmonte Tel´fono: 1234 e Muestra informaci´n llamando a los m´todos de la clase. escribimos tras new un constructor de la clase. "Belmonte". telefono). F´ ıjate que a la izquierda de new tenemos Persona unaPersona =. o e Nombre: ´scar O Apellidos:Belmonte Tel´fono: 1234 e Como has comprobado. mientras que en las l´ ıneas 17-19 accedemos a la misma informaci´n haciendo uso de los m´todos definidos en la clase (getNombre(). en las siguientes secciones veremos con m´s detalle qu´ significa el concepto variable de tipo referencia.2. para mostrar informaci´n en forma de texto por consola utilio zamos System.java o que tienes en la columna de la derecha en Eclipse (Package Explorer ) y en el men´ emergente que te aparecer´ selecciona Run as → Java Application. vemos c´mo se usa el operador new u o para crear una instancia de la clase. getTelefono()). para ello haz click con el bot´n derecho sobre el nombre de la clase Principal. u En las l´ ıneas 12-14 recuperamos la informaci´n a partir de la variable de o tipo referencia a Persona accediendo directamente a sus atributos (nombre. apellidos. MIEMBROS DE UNA CLASE 31 Listado 2.new utilizar´ el O a constructor con tres argumentos de la clase Persona para crear una nueva instancia.7: C´digo de la clase Principal o La clase Principal est´ repleta de novedades. Finalmente. u a en la parte inferior de Eclipse se abrir´ una nueva solapa (Console) donde se a mostrar´ el resultado de la ejecuci´n que debe ser: a o Muestra informaci´n accediendo directamente a los campos. en este caso Persona("´scar". o e getApellidos().

Definici´n o El nombre de un m´todo junto con su lista de argumentos forman la signatura e del m´todo. Por ejemplo en el siguiente Listado los dos m´todos unMetodo est´n e a sobrecargados y son distintos. String telefono). String apellidos. En caso de que los dos m´todos tengan el mismo e n´mero de argumentos. e En el siguiente Listado se muestra un error al intentar sobrecargar dos m´toe dos que se distinguen unicamente por su tipo de retorno. no los podremos sobrecargar u haciendo que el tipo de sus valores de retorno sean distintos. ser´n distintos si al menos un tipo de sus argumentos u a es distinto. 2. ´ // LOS METODOS NO SE PUEDEN SOBRECARGAR POR EL TIPO DE RETORNO. ´ 1 2 3 4 5 6 7 8 9 // ESTE LISTADO CONTIENE UN ERROR.6. Si dos m´todos tienen el mismo e e n´mero de argumentos y sus tipos son los mismos. ¿Qu´ sentido tiene declarar e e m´todos de acceso a los atributos de una clase si puedo acceder directamente a e ellos?.32 CAP´ ITULO 2. p u b l i c v o i d unMetodo ( ) { // D e f i n i c i ´ n d e l m´ todo o e } p u b l i c i n t unMetodo ( ) { // D e f i n i c i ´ n d e l m´ todo o e } Los dos m´todos tienen el mismo nombre y ning´n argumento.2. esta clase tiene dos constructores Persona() y Persona(String nombre. y el segundo de ellos retorna un int. el primero de e u ellos no retorna nada void. Un detalle muy importante en la sobrecarga de m´todos es que el tipo de e retorno no sirve para distinguir dos m´todos. 1 2 3 4 5 6 7 p u b l i c v o i d unMetodo ( i n t e n t e r o ) { // D e f i n i c i ´ n d e l m´ todo o e } p u b l i c v o i d unMetodo ( f l o a t r e a l ) { // D e f i n i c i ´ n d e l m´ todo o e } De modo an´logo. CLASES Pregunta En el ejemplo anterior estamos recuperando la informaci´n almacenada en una o instancia de la clase Persona de dos modos: accediendo directamente a sus atributos. El compilador es .4. El tipo del valor de retorno no forma parte de la signatura de un e m´todo. o llamando a los m´todos de la clase. Sobrecarga de m´todos y constructores e Dos o m´s m´todos pueden tener el mismo nombre siempre que su n´mero a e u de argumentos sea distinto. los constructores tambi´n pueden estar sobrecargados. a e de hecho hemos sobrecargado el constructor de la clase Persona en el Listado 2.

1.3. e En Java. En Java existen dos grandes grupos de tipos de datos. booleanos. e e 2.3. es muy importante asimilar la diferencia entre variables de tipo primitivo y variables de tipo referencia. no con tipos primitivos. Los tipos de datos primitivos y sus tama˜os son los que aparecen en n la Tabla 2. Tipos de datos en Java. Una variable de tipo referencia establece una conexi´n hacia un objeto. los tipos de datos referencia nos permiten indicar que vamos a trabajar con instancias de clases. el tama˜o en memoria de los tipos de datos primitivos est´ estann a darizado. sino que nos permiten acceder a los atributos y m´todos de los objetos. las instancias de clases. Se les u u e llama primitivos porque nos permiten manejar elementos de informaci´n b´sicos o a como letras y n´meros. Las variables de tipo referencia no almacenan u valores. los tipos de datos primitivos y los tipos de datos referencia. e Por otro lado. TIPOS DE DATOS EN JAVA. pero el las variables de tipo referencia no almacenamos valores son la puerta de entrada hacia los objetos. e Concepto Las variables de tipo primitivo nos permiten almacenar valores de tipo primitivo como n´meros y caracteres. e Cuando hablamos de variables. Una variable de tipo primitivo nos permite almacenar u en ella un tipo primitivo como por ejemplo un valor num´rico. Son los objetos. caracteres. Tipo boolean char byte short int long float double Tama˜ o(bits) n 1 16 8 16 32 64 32 64 33 Definici´n o true o false Car´cter Unicode a Entero en complemento a dos con signo Entero en complemento a dos con signo Entero en complemento a dos con signo Entero en complemento a dos con signo Real en punto flotante seg´n la norma IEEE 754 u Real en punto flotante seg´n la norma IEEE 754 u Tabla 2. etc´tera. Los tipos de datos primitivos sirven para representar tipos de datos tales como n´meros enteros. n´meros reales. e Pero volvamos a Java y vemos qu´ significa el t´rmino tipo de dato referencia.1: Tipos de datos primitivos en Java y sus tama˜os en memoria. n incapaz de distinguirlos y devuelve un error que indica que estamos intentando definir el mismo m´todo dos veces. En una variable de tipo primitivo podemos almacenar valores de tipo primitivo (n´meros.2. y a trav´s de esta conexi´n o e o podremos acceder a sus atributos y m´todos. . las que almacenan informaci´n y me permiten trabajar con ellos a trav´s de o e llamadas a sus m´todos. cau racteres).

por ejemplo. // Array iniciado Los arrays de tipos referencia se declaran: Ejemplo 3 : Persona grupo[]. Ejemplo 2 : Persona persona = new Persona("´scar". las referencias en Java son la puerta de entrada a los objetos. // Array declarado Ejemplo 2 : int arrayEnteros[] = new int[10]. "P´rez". // Array declarado Ejemplo 4 : Persona grupo = new Persona[10]. Sintaxis Las variables de tipo referencia se declaran de este modo: tipoReferencia nombre [ = valor referencia inicial]. las referencias me permiten acceder a los atributos y m´todos de los e objetos. Ejemplo 1 : Persona persona. 2. Esto nos sirve para crear una unica ´ variable que contendr´ bien un tipo de datos primitivo a una referencia a un a objeto. Hasta el momento.3. En Java utilizaremos arrays de elementos cuando necesitemos manejar m´s a de un elemento del mismo tipo.14f. nos interesa trabajar con m´s de un unico valor u a ´ de un determinado tipo. Veamos c´mo podemos declarar conjuntos o de elementos del mismo tipo en Java. Ejemplo 2 : float pi = 3. hemos aprendido c´mo declarar variables de tipos de datos o primitivos y de tipos de datos referencia. . el tipo de una referencia debe ser compatible con el tipo del objeto al que se refiere.1. En el cap´ ıtulo 3 dedicado a la herencia veremos qu´ quiere decir e ((compatible)). O e En m´ltiples ocasiones. Arrays de datos en Java. Ejemplo 1 : int hojas. en vez de trabajar con una unica Persona queremos ´ trabajar con un grupo de personas. Para declarar un array en Java utilizamos los corchetes seg´n la siguiente sintaxis: u Sintaxis Los arrays de tipos primitivos se declaran: Ejemplo 1 : int array[]. // Array iniciado Aunque la sintaxis de la declaraci´n de arrays de tipo primitivo y de tipo o referencia es la misma. //f´jate en la f al final del n´mero ı u Como ya hemos visto. el resultado es radicalmente distinto en los dos casos. CLASES Sintaxis Las variables de tipo primitivo se declaran de este modo: tipo nombre [ = valor inicial]. "123").34 CAP´ ITULO 2. en alguna circunstancia nos puede interesar declarar una variable con la que poder acceder a un grupo de 10 enteros o 100 objetos de la clase Persona. pero a veces nos interesa poder manejar conjuntos de elementos del mismo tipo.

en los arrays de tipo referencia no se ha creado ninguna instancia de la clase correspondiente. Dicho de otro modo No se ha creado ning´ n objeto u de la clase Persona. } } Listado 2. 35 Analic´moslo. pero la o referencia que tenemos en la posici´n 5 del array de tipo Persona es el valor o por defecto null que en Java tiene el significado de Referencia no asignada. nombre ) . // Se p r o d u c e un e r r o r .Arrays. p r i n t l n ( " N o m b r e e n p o s i c i ´ n g r u p o P e r s o n a s [ 5 ] : " + o g r u p o P e r s o n a s [ 5 ] . si no una referencia a un objeto de tipo Persona.java:15) En la posici´n 5 del array de enteros tenemos un valor por defecto. Mientras que en el caso de los arrays de tipo primitivo. s´lo referencias a objetos de ese tipo. . En el caso del Ejemplo 4. o u t .NullPointerException at hola. no hay nada en l a p o s i c i ´ n [ 5 ] o System . P e r s o n a g r u p o P e r s o n a s [ ] = new P e r s o n a [ 1 0 ] . En este caso.2.3. En el Ejemplo 2 del recuadro de sintaxis anterior se est´ definiene a do un array capaz de albergar 10 enteros (con ´ ındice 0 para el primer elemento e ´ ındice 9 para el ultimo). lo que tenemos en cada una de las posiciones del array no es un objeto de tipo Persona. estamos definiendo un array capaz de albergar 10 ((referencias)) de tipo Persona. y luego Run o as → Java Applications). y estos objetos los habremos creado en otro lugar de nuestro programa. // La s i g u i e n t e s e n t e n c i a e s v a l i d a System . Veamos esta diferencia con el siguiente ejemplo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package agenda . o u t .main(Arrays. TIPOS DE DATOS EN JAVA.lang. obtendr´s el siguiente error: a Valor en arrayEnteros[5]: 0 Exception in thread "main" java. dentro de cada una de las posiciones del array podemos ´ almacenar un entero.8: Diferencia entre arrays de tipos primitivos y arrays de tipos referencia Si creas una nueva clase con el c´digo del Listado 2. lo unico que se ha crea´ do es un conjunto de referencias que podremos conectar a objetos de la clase correspondiente. public c l a s s A r r a y s { /∗ ∗ ∗ @param a r g s ∗/ public s t a t i c void main ( S t r i n g [ ] a r g s ) { // TODO Auto−g e n e r a t e d method s t u b i n t a r r a y E n t e r o s [ ] = new i n t [ 1 0 ] .8 y lo ejecutas (recuerda: o bot´n derecho sobre el nombre de la clase en el Package Explorer. p r i n t l n ( " V a l o r e n a r r a y E n t e r o s [ 5 ] : " + a r r a y E n t e r o s [ 5 ] ) . una vez creados ya tenemos disponible en cada una de sus posiciones espacio para albergar un elemento del tipo correspondiente. o La diferencia entre arrays de tipo primitivo y tipo referencia es muy importante.

La respuesta o es: ((Usando estructuras de control de repetici´n)) o 2. p r i n t l n ( " V a l o r e n a r r a y E n t e r o s [ 5 ] : " + a r r a y E n t e r o s [ 5 ] ) . o Estructuras de control de selecci´n: Nos permiten especificar mas de una o direcci´n de flujo dependiendo de alguna condici´n. la pregunta que nos o surge es ¿C´mo puedo recorrer todos los elementos de un array?. // Se p r o d u c e un e r r o r . Dentro de este operador indicamos la posici´n del elemento a la que deseamos acceder. Ya sabemos c´mo acceder a los elementos de un array. o o . P e r s o n a g r u p o P e r s o n a s [ ] = new P e r s o n a [ 1 0 ] . " G o s s l i n g " . // La s i g u i e n t e s e n t e n c i a e s v a l i d a System . o ¿C´mo podemos resolver el error anterior?. } } Si ejecutas el c´digo con la modificaci´n obtendr´s el siguiente resultado: o o a Valor en arrayEnteros[5]: 0 Nombre en posici´n grupoPersonas[5]: James o En este ultimo caso la referencia en la posici´n 5 del array grupoPersonas ´ o s´ que hace referencia a un objeto. o u t . Estructuras de control. o u t . nombre ) . esto significa que Java proo porciona estructuras de control para decidir el flujo de ejecuci´n de nuestros o programas.36 Sintaxis CAP´ ITULO 2. p r i n t l n ( " N o m b r e e n p o s i c i ´ n g r u p o P e r s o n a s [ 5 ] : " + o g r u p o P e r s o n a s [ 5 ] . no hay nada en l a p o s i c i ´ n [ 5 ] o System . public c l a s s A r r a y s 2 { /∗ ∗ ∗ @param a r g s ∗/ public s t a t i c void main ( S t r i n g [ ] a r g s ) { // TODO Auto−g e n e r a t e d method s t u b i n t a r r a y E n t e r o s [ ] = new i n t [ 1 0 ] . Existen dos grandes grupos de estructuras de control: Estructuras de control de repetici´n: Nos permiten indicar si un determio nado bloque de c´digo se debe ejecutar mas de una vez. " 5 5 5 1 2 3 4 5 6 " ) . CLASES A los elementos de un array se accede mediante el operador []. luego no hay problema al usarla para acceder ı a su atributo nombre. g r u p o P e r s o n a s [ 5 ] = new P e r s o n a ( " J a m e s " .4. Simplemente asignando a la reo ferencia en la posici´n 5 del array grupoPersonas una referencia a un objeto o que haya sido creado: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package agenda . Java es un lenguaje de programaci´n estructurado.

Bucle while.4.each introducido en la versi´n 5 de Java. o En Java existen tres estructuras de control de repetici´n: o Bucle for.. i ++) .. En el segundo ejemplo se utiliza el bucle for.1.. uno con cada iteraci´n. Bucle do. Veamos un ejemplo con un poco m´s de detalle: a 1 2 3 4 5 6 7 8 9 package r e p e t i c i o n . luego la variable toma los valores 0. public c l a s s B u c l e F o r { public s t a t i c void main ( S t r i n g [ ] a r g s ) { // Declaramos e l a r r a y i n t a r r a y E n t e r o s [ ] = new i n t [ 5 ] . la condici´n de parada es que el valor de la variable o sea menor que 10 y el incremento en cada paso del bucle es 2.. El bucle for Si conocemos cual es el primer elementos y el ultimo sobre los que queremos ´ iterar el bucle for es la manera m´s c´moda de recorrerlos todos. i <10..while..1. En este caso utilizamos una variable que va recibiendo los valores o de los elementos que hay dentro del conjunto de manera incremental. al o salir del bucle desaparece la variable de control ((i)). 37 2.each: for(Tipo variable: Colecci´n) o Ejemplo 2 : int arrayEnteros [] = new int[10].1.. para. En el caso de un array nos sirven para o recorrer los elementos almacenados en el array secuencialmente.4.each es especialmente util cuando se itera sobre o ´ los elementos de una colecci´n. tal y como veremos en el Cap´ o ıtulo 8.2. o 2. mostrar sus valores. ESTRUCTURAS DE CONTROL. condici´n: incremento) o Ejemplo 1: for(int i = 0. Las estructuras de repetici´n sirven para repetir una determinada tarea o mientras se cumpla cierta condici´n. Su sintaxis a o es la siguiente: Sintaxis La sintaxis del bucle for es: for(inicio. 6 y 8. // Almacenamos d a t o s en s u s e l e m e n t o s f o r ( i n t i = 0 .4. 4. Veamos como se usa cada una de estas estructuras de repetici´n. for(int i: arrayEnteros) En el primer ejemplo del recuadro de sintaxis se utiliza una variable de control que se inicia a 0. i < 5 . El bucle for.. 2. por ejemplo. i += 2) La variable ((i)) se declara en el bucle y s´lo tiene existencia dentro del bucle. Estructuras de control de repetici´n. Para el bucle for.

o . El bucle do.while En el caso del bucle do. si la condici´n de parada no involucra el valor o de una posicion podemos utilizar el bucle while si necesitamos comprobar la condici´n antes. si la condici´n se cumple.while la condici´n se comprueba despu´s de haberse o e ejecutado al menos una vez el cuerpo del bucle. La condici´n se comprueba al o final del bucle.3. CLASES arrayEnteros [ i ] = i . Elegir una u otra depende n de cada caso: si conocemos el intervalo sobre el que queremos iterar el bucle for es el mas comodo de utilizar.1.while es: do { Bloque de c´digo o } while(condici´n). o o Sintaxis La sintaxis del bucle while es: while(condici´n) { o Bloque de c´digo o } 2. la condici´n de parada se comprueba antes de cada o iteraci´n y. o Estas tres estructuras de control de repetici´n son intercambiables. se ejecuta el bloque del bucle while.1.4.while si queremos ejecutar al menos una o vez el bloque de c´digo que encierra el bucle.38 10 11 12 13 14 15 16 CAP´ ITULO 2. El segundo bucle itera sobre las u posiciones del array y muestra el valor almacenado en cada una de ellas.2. // Lo r e c o r r e m o s y e x t r a e m o s l a i n f o r m a c i ´ n almacenada o for ( int i : arrayEnteros ) System . } } El resultado de la ejecuci´n de este c´digo es el siguiente: o o arrayEnteros[0] arrayEnteros[1] arrayEnteros[2] arrayEnteros[3] arrayEnteros[4] = = = = = 0 1 2 3 4 El primer bubcle for itera sobre las posiciones del array almacenando los n´meros 0 a 4 en las posiciones 0 a 4 del array...4... se puede o sustituir una por otra con peque˜as modificaciones... p r i n t l n ( " a r r a y E n t e r o s [ " + i + " ] = " + a r r a y E n t e r o s [ i ] ) .. o u t . o bien el bucle do.. 2. Sintaxis La sintaxis del bucle do. El bucle while En el caso del bucle while.

p r i n t l n ( " E l m e s e s E n e r o . p r i n t l n ( " E l n ´ m e r o e s p a r . La condici´n debe evaluarse a un valor booleano. o u t . p r i n t l n ( " E l n ´ m e r o e s i m p a r . se ejecuta el c´digo correspondiente al case hasta que se encuentra la sentencia o break en cuyo momento se avandona el bloque de la sentencia switch.2. a a o 2. En o o este caso el camino a seguir se selecciona bas´ndose en el valor de una expresi´n a o que se evalua a un valor entero. u e l s e System . o Las estructuras de control de selecci´n nos permiten especificar mas de un posio ble camino a seguir por el flujo de ejecuci´n de nuestro programa. default : System . y se prueba cada una de las opciones expresadas por un case. ESTRUCTURAS DE CONTROL.2. se evalua el valor de la variable mes.. o u t .else. Estructuras de control de selecci´n.2. La sentencia if nos permite ejecutar un bloque de c´digo. como en el siguiente ejemplo: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 i n t mes = 1 . case 2 : System . Exite una . " ) . } En el ejemplo anterior. o u t . " ) . o u t . u Dentro del bloque de c´digo correspondiente al else podemos a˜adir una o n nueva sentencia if. " ) . o o 2. " ) .4. Cuando coinciden los valores.1. dependiendo o de cierta condici´n. " ) . " ) . p r i n t l n ( " E l m e s e s F e b r e r o .4. break . como en el siguiente ejemplo de c´digo: o 1 2 3 int entero . es decir. p r i n t l n ( " E l m e s e s M a r z o .2. o u t . // C o r r e s p o n d e a l mes de Enero s w i t h ( mes ) { case 1 : System . a como en el siguiente ejemplo: 1 2 3 4 5 6 7 i f ( primeraCondicion ) { \\ Bloque de c o d i g o ´ } e l s e i f ( segundaCondicion ) { \\ Bloque de c o d i g o ´ } else { \\ Bloque de c o d i g o ´ } Esto nos permite especificar m´s de un posible camino a seguir por el flujo a de ejecuci´n de nuestro c´digo. o u t .4. case 3 : System . 39 2. i f ( e n t e r o % 2 == 0 ) System . break . se dice entonces que las sentencias if est´n encadenadas. M´ ltiples caminos con la sentencia switch u Existe una construcci´n del lenguaje que nos permite especificar m´ltiples camio u nos a seguir por el flujo de ejecuci´n de nuestro c´digo: la sentencia switch. break . break .. La direcci´n o o final que seguir´ el flujo depender´ de si se cumple o no cierta condici´n. o o a true o false.2.4. Bifurcaciones con la sentencia if. p r i n t l n ( " N i n g u n o d e l o s m e s e s a n t e r i o r e s . o no.

La respuesta a la pregunta anterior hace surgir una nueva: ¿C´mo restrino jo la visibilidad de los atributos de una clase?. ” ) . la respuesta es: mediante los Modificadores de acceso. para acceder a los valores de los atributos utilizaremos m´todos. p r i n t l n ( ” El mes break . o u t . 6. se ejecuta su c´digo correspondiente hasta o o encontrar la sentencia break. e o una de las piezas centrales de la programaci´n orientada a objetos. nunca debemos hacer visibles los atributos de nuestras clases. 2. Esta regla es una manera de expresar el concepto de Encapsulaci´n. 5. al seleccionar uno de ellos se ejecutar la sentencia de la l´ ınea 10. Ahora ya estamos en situaci´n de volver a la pregunta: ¿Qu´ sentido tiene declao e rar m´todos de acceso a los atributos de una clase si puedo acceder directamente e a ellos? La repuesta es que. CLASES opci´n Por defecto etiquetada como default que es opcional y cuyo c´digo se o o ejecutar´ si la expresi´n entera no coincide con ninguno de los case anteriores. o u t . } mes de Enero t i e n e 31 d´a s . Como resultado. p r i n t l n ( ” El mes break . Lo mismo ocurrir´ si el ordinal del mes es a 4. o Concepto Las clases encapsulan atributos y m´todos de tal modo que s´lo se hace visible e o una parte de esos atributos y m´todos. 10 o 12 tienen 31 d´ todos los case correspondientes. Esto nos permite obviar esta sentencia si queremos que varios case distintos ejecuten el mismo segmento de c´digo. 7. ı es Febrero .5. excepto el de valor 12. // C o r r e s p o n d e a l s w i t c h ( mes ) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: System . sentencia break por lo que en todos los casos. los estrictamente necesarios para que e podamos trabajar con las instancias de esa clase. 3. Modificadores de acceso. 8. ı t i e n e 30 d´a s . en todos los casos se ejecutar´ la sentencia de la l´ a ınea 16. como en el o siguiente ejemplo: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 i n t mes = 1 . ” ) . a o Es importante hacer notar que una vez que se encuentra una coincidencia entre la expresi´n entera y un case. 9 u 11. como regla general. En el ejemplo anterior los meses cuyo ordinal es 1. p r i n t l n ( ” El mes break : default : System . s´lo deben ser visibles desde el interior de las o clases. ” ) . no incluye la ıas. . case 4: case 6: case 9: case 11: System . o u t .40 CAP´ ITULO 2.

} String getApellidos () { return a p e l l i d o s . y hasta que veamos el cap´ ıtulo de herencia. vamos a ver el significado de los dos m´s sencillos: private y public. public c l a s s P e r s o n a { S t r i n g nombre . String telefono . ((Vac´ (no escribimos nada). a p e l l i d o s = a p e l l i d o s . t e l e f o n o = t e l e f o n o . ıo)) public. estamos haciendo visibles los m´todos de la clase a cualquier otra clase que los quiera utilizar e (modificador public). Por otro lado. S t r i n g a p e l l i d o s . . } } String telefono ) { En este caso estamos restringiendo la visibilidad de los atributos de la clase Persona de modo que unicamente son visibles desde el interior de la propia clase ´ donde se han definido (modificador private). Persona ( ) { } P e r s o n a ( S t r i n g nombre . this . e En Java un modificador de acceso est´ representado por una palabra resera vada que me permite definir la visibilidad de un atributo o un m´todo de la e clase.5. nombre = nombre . this . De momento. } S t r i n g getNombre ( ) { return nombre . Los modificadores de a acceso se escriben antes del tipo del atributo o antes del tipo de retorno del m´todo. } String getTelefono () { return t e l e f o n o . String apellidos . t h i s . MODIFICADORES DE ACCESO.2. 41 Definici´n o Los modificadores de acceso son palabras reservadas de Java mediante las cuales restringimos la visibilidad de los atributos y m´todos de una clase. Los cuatro modificadores de acceso que podemos utilizar en Java son: private. protected. Veamos c´mo quedar´ nuestra clase Persona asignando la visibilidad e o ıa adecuada a cada uno miembros: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package agenda .

Pero existe una restricci´n. private S t r i n g t e l e f o n o . Un atributo de una clase se puede modificar con la palabra reservada static. se considera una buena pr´ctica declarar los atributos de una clase a como privados (private) y si necesitamos acceder a ellos para leer sus valores o modificarlos utilizaremos los m´todos get o set. En caso de que el tipo del valor e devuelto sea boolean se utilizar´ is en vez de set. iniciaAtributos () .6. En el siguiente ejemplo de c´digo se est´ utilizando este m´todo a o a e est´tico a trav´s del nombre de la clase y a trav´s de una instancia concreta: a e e . podemos usarlos a trav´s del nombre de la clase. y. pero nunca a atributos o m´todos que no lo sean. al igual que e e con los atributos static. private s t a t i c i n t n I n s t a n c i a s . A estos m´todos se les llama m´todos de la clase. Por ello. pues que no existe una copia de ese e atributo en cada uno de los objetos de la clase. } public s t a t i c i n t g e t N I n s t a n c i a s ( ) { return n I n s t a n c i a s . los o m´todos est´ticos de una clase s´lo pueden acceder a atributos est´ticos u otros e a o a m´todos est´ticos de la clase. ¿Qu´ quiere decir esto?. por ejemplo isNuevo() en a vez de getNuevo() si el valor que se retorna es un boolean (true o false). e De igual modo. public c l a s s P e r s o n a implements C o n t a c t o { private S t r i n g nombre . podemos acceder a ellos a trav´s del nombre de la clase. si no que existe una unica copia ´ que es compartida por todos los objetos de la clase. CLASES Buenas pr´cticas y convenciones a En general. podemos modificar los m´todos de una clase con la palabra e reserva static. en Java existen otros modificadores que tambi´n e e se pueden aplicar sobre la definici´n de atributos y m´todos: static y final. } F´ ıjate que el m´todo getNInstancias() que accede al atributo nInstancias e es est´tico. Modificadores static y final. private S t r i n g a p e l l i d o s . o e 2. Adem´s de los modificadores que nos permiten definir la visibilidad de atria butos y m´todos de una clase. sin e necesidad de crear ninguna instancia de la clase.42 CAP´ ITULO 2. con ello indicamos que el atributo no pertenece a las instancias de la clase si no a la propia clase. public P e r s o n a ( ) { super ( ) . a los atributos static se les llama atributos de la clase. Una consecuencia de lo anterior es que para acceder a los atributos static de una clase no necesitamos crear una instancia de la clase. e a e ¿Ves porqu´? ¿Qu´ ocurrir´ si desde un m´todo est´tico y usando el nombre e e ıa e a de la clase intentases acceder a un atributo de instancia de la clase? En el siguiente ejemplo de c´digo hemos a˜adido un contador para saber el o n n´mero de instancias de la clase Persona que se han creado: u 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package t i p o s .

El recolector de basura conoce en todo momento todas las referencia que una instancia posee.7. p r i n t l n ( " N u m e r o d e p e r s o n a s c r e a d a s : " + P e r s o n a . } De este modo. . por ejemplo: 1 private f i n a l S t r i n g a u t o r = " ´ s c a r " . o u t . si lo intent´semos a cambiar el compilador nos dar´ un error. la constante es accesible desde cualquier otra clase (al ser public) y podemos leerla a trav´s del nombre de la clase de este modo e Constantes. } private void e j e c u t a ( ) { P e r s o n a unaPersona = new P e r s o n a ( ) .7. " G o s s l i n g " . el compilador de Java nos dar´ un error.2. 43 1 2 3 4 5 6 7 8 9 10 11 public f i n a l c l a s s P r i n c i p a l { private P r i n c i p a l ( ) { super ( ) . " 5 5 5 1 2 3 4 5 6 " ) . EL RECOLECTOR DE BASURA. a Regla de convenci´n o Los nombre de las constantes se escriben en may´sculas. 2. el Recolector de basura. // Accedemos a l m´ todo a t r a v ´ s de l a c l a s e e e System . P e r s o n a o t r a P e r s o n a = new P e r s o n a ( " J a m e s " .. como en el siguiente ejemplo: 1 2 3 4 public c l a s s C o n s t a n t e s { public s t a t i c f i n a l double PI = 3 . Veremos con detalle lo que esto significa en el Cap´ ıtulo 3 dedicado a la herencia en Java. el modo de acceder a los objetos en Java es mediante las variables de tipo referencia.. El recolector de basura. // Accedemos a l m´ todo a t r a v ´ s de una i n s t a n c i a c o n c r e t a e e Cuando un atributo de una clase los modificamos en su definici´n con la o palabra reservada final. 1 4 1 5 9 2 . Si un objeto pierde . a Como ya sabes. Para liberar la memoria existe un mecanismo mucho m´s potente. ´ getNInstancias () ) . ıa Muchas veces los modificadores static y final se utilizan en combinaci´n o para definir constantes. Hemos visto que para crear instancias de una clase utilizamos el operador new. u El modificador final tambi´n se puede usar sobre un m´todo o sobre la e e clase. este atributo no puede cambiar de valor. pero si por descuido intentamos modificarla. y de igual modo conoce cuando una instancia ha perdido todas las referencias que apuntaban a ella. estamos indicando que ese atributo no puede cambiar de valor. Cuando ya no necesitamos una instancia: ¿C´mo liberamos el espacio en memoo ria que est´ ocupando? En Java no existe ning´n operador especial para eliminar a u de la memoria las instancias que no vamos a seguir utilizando. O Una vez definido.PI.

en el ıa ıa m´todo finalize podemos escribir el c´digo que cierre los ficheros que est´n e o a abiertos. sabemos que lo har´. como norma general: . getRuntime ( ) . ¿C´mo podemos marcar un objeto para que sea borrado de memoria? Una o t´cnica sencilla es eliminar todas las referencias que apuntan a ´l como en el e e siguiente ejemplo: 1 2 3 4 5 P e r s o n a u n a R e f e r e n c i a = new P e r s o n a ( ) . r . gc ( ) . Dicho de otro modo. // E st a P e r s o n a t i e n e una r e f e r e n c i a hacia e l l a P e r s o n a o t r a R e f e r e n c i a = u n a R e f e r e n c i a . ´ no se garantiza que el recolector de basura vaya a ser invocado inmediatamente. eliminar´ esta instancia de la memoria y el resultado ıa colateral ser´ que el fichero quedar´ abierto. e a Sup´n que has escrito un clase que abre un fichero para lectura (veremos o acceso a ficheros en el cap´ ıtulo 7). o En la secci´n anterior hemos visto cual es el mecanismo que utiliza Java para o ir liberando de la memoria los objetos que ya no son accesibles. Todos los objetos poseen un m´todo con la siguiente signatura protected void finalize() e throws Throwable. el m´todo finalize es la ultie ´ ma oportunidad que tenemos como programadores para que nuestras instancias acaben limpiamente.8. significa que ya no podremos acceder a ese objeto. as´ como la clase Throwable. pero a no sabemos cuando. Veamos qu´ quiere decir esto con m´s detalle. // S o l i c i t a m o s que e l r e c o l e c t o r de b a s u r a e n t r e en a c c i o n . el problema que conlleva delegar al m´todo e finalize estas tareas de limpieza segura antes de acabar es que no sabemos cuando el recolector de basura va a hacer su trabajo. // Ahora t i e n e dos u n a R e f e r e n c i a = n u l l . Para que esto no ocurra. y que por cualquier motivo una instancia de esta clase pierde todas las referencias que apuntan a ella. Cuando actuase el recolector de basura. Pero no es tan inmediato. // Le d e s c o n e c t a m o s l a p r i m e r a r e f e r e n c i a o t r a R e f e r e n c i a = n u l l . de modo que el recolector de basura puede hacer su trabajo: liberar la memoria ocupada por la instancia. Y aunque podemos ((forzar)) la actuaci´n del recolector de o basura de este modo: 1 2 Runtime r = Runtime . ı lo que nos interesa en este momento es saber que este es el ultimo m´todo de ´ e cualquier objeto que se llama antes de que el recolector de basura elimine la instancia de la memoria. CLASES todas la referencias que apuntan a ´l y las referencias son el unico mecanismo e ´ que tenemos de acceder a los objetos. // Le d e s c o n e c t a m o s l a segunda r e f e r e n c i a // El r e c o l e c t o r de b a s u r a ya puede h a c e r su t r a b a j o 2. Finalizaci´n. en los cap´ ıtulos siguientes veremos con detalle el significado de las palabras reservadas protected y throws.44 CAP´ ITULO 2. ya que sabemos que este m´todo ser´ llamado antes de eliminar la e a instancia de memoria. Luego.

Comentarios de m´s de una l´ a ınea. Comentarios. Pero. sin duda. n o o podemos utilizar la etiqueta para indicar quien es el autor del c´digo de una o clase. Comentarios de documentaci´n. Buenas pr´cticas a 45 No debemos delegar en el recolector de basura la limpieza que han de realizar nuestras clases cuando sus instancias son eliminadas de memoria. /∗ E s t e c o m e n t a r i o ocupa m´s de una l´ n e a a ı de c o d i g o ∗/ ´ private S t r i n g a p e l l i d o s . el texto del comentario puede ocupar cuantas l´ ıneas necesitamos. Un comentario de documentaci´n siempre debe empezar por /**. Dentro de los comentarios de documentaci´n podemos utilizar etiquetas para o a˜adir informaci´n que enriquezca la documentaci´n generada. o Todos los programadores son conscientes de la importancia de documentar su trabajo. y debe acabar por */. Comentarios de documentaci´n. Por ejemplo. Los comentarios de m´s de una l´ a ınea empiezan con /*.9. 2. crear documentaci´n de nuestro c´dio o o go en formato html. COMENTARIOS. Veamos c´mo o o se introducen los comentarios de documentaci´n y las etiquetas que tenemos o disponibles. 2. o o Para realizar tareas de documentaci´n Java nos proporciona tres tipos de o comentarios: 1. En el siguiente ejemplo puedes ver c´mo se usan ambos tipos de comentario: o 1 2 3 4 5 6 7 public c l a s s P e r s o n a { // e s t o e s un c o m e n t a r i o de una u n i c a l´ n e a ´ ı private S t r i n g nombre . pero es necesario indicar que el comentario acaba insertando al final */.9. como en el siguiente ejemplo: 1 /∗ ∗ I m p l e m e n t a c i o n de l a ´ c l a s e Persona .´ 2. nota que o tras la barra se escriben dos asteriscos. los comentarios de documentaci´n son una herramienta realo mente potente en Java. como los comentarios de m´s de una l´ a ınea. Los comentarios de documentaci´n se incluyen en el o c´digo y nos sirven para. Una tarea de documentaci´n es incluir comentarios en el propio c´digo o o para que otros programadores puedan conocer en el momento de la lectura de c´digo los detalles de implementaci´n. o Los comentarios de una unica l´ ´ ınea empiezan con y el texto del comentario restringe su extensi´n a una unica l´ o ´ ınea. COMENTARIOS DE DOCUMENTACION. En los comentarios de documentaci´n podemos a˜adir etio n quetas que nos permiten enriquecer la documentaci´n generada. 3. Comentarios de una unica l´ ´ ınea. a partir de ellos.

46
2 3 4 5 6 7 8 9

CAP´ ITULO 2. CLASES
Es ta c l a s e d e s c r i b e a un nuevo c o n t a c t o en una agenda de t e l ´ f o n o s e ´ @author Oscar Belmonte Fern´ ndez a @version 1.0

∗ ∗ ∗ ∗ ∗/

public c l a s s P e r s o n a { private S t r i n g nombre ;

otros comentarios de documentaci´n: o @version Indicamos la versi´n del c´digo. o o @param nombre Descripci´n del par´metro. o a @return Significado del valor de retorno. @deprecated Raz´n de por qu´ este m´todo est´ obsoleto. o e e a @see #metodo() Referencia cruzada al m´todo. e @exception Excepci´n que se puede producir en el m´todo o e @throws Excepci´n no gestionada o Adem´s, en los comentarios de documentaci´n podemos incluir c´digo HTML. a o o En el listado 2.9 tienes la clase Persona documentada.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

package p e r s o n a . c o m e n t a r i o s ; /∗ ∗ I m p l e m e n t a c i o n de l a c l a s e P e r s o n a ´ ∗ Es ta c l a s e d e s c r i b e a un nuevo c o n t a c t o ∗ en una agenda de t e l ´ f o n o s e ´ ∗ @author Oscar Belmonte Fern´ ndez a ∗ @version 1.0 ∗/ public c l a s s P e r s o n a { private S t r i n g nombre ; private S t r i n g a p e l l i d o s ; private S t r i n g t e l e f o n o ; private s t a t i c i n t n I n s t a n c i a s = 0 ; /∗ ∗ ∗ C ons t ru ct or por d e f e c t o ∗/ public P e r s o n a ( ) { n I n s t a n c i a s ++; } /∗ ∗ ∗ C o n s t r u c t o r con p a r a m e t r o s . ´ ∗ En n u e v a s v e r s i o n e s , t a n t o e l nombre como l o s a p e l l i d o s s e r a n ´ ∗ i n m u t a b l e s , no e x i s t i r ´ n m´ todos p a r a c a m o b i a r l o s a e ∗ @param nombre Nombre d e l nuevo c o n t a c t o ∗ @param a p e l l i d o s A p e l l i d o s d e l nuevo c o n t a c t o ∗ @param t e l e f o n o T e l ´ f o n o d e l nuevo c o n t a c t o e ∗/ public P e r s o n a ( S t r i n g nombre , S t r i n g a p e l l i d o s , S t r i n g t e l e f o n o ) { t h i s . nombre = nombre ; this . a p e l l i d o s = a p e l l i d o s ; this . t e l e f o n o = t e l e f o n o ; n I n s t a n c i a s ++; } /∗ ∗ ∗ D e v u e l v e e l n´ mero de i n s t a n c i a s c r e a d a s u ∗ @ re t ur n El n´ mero de i n s t a n c i a s u

´ 2.9. COMENTARIOS. COMENTARIOS DE DOCUMENTACION.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97

47

∗/ public s t a t i c i n t g e t N I n s t a n c i a s ( ) { return n I n s t a n c i a s ; } /∗ ∗ ∗ D e v u e l v e e l nombre d e l c o n t a c t o ∗ @re t ur n Nombre d e l c o n t a c t o ∗/ public S t r i n g getNombre ( ) { return nombre ; } /∗ ∗ ∗ Devuelve l o s a p e l l i d o s d e l c o n t a c o t ∗ @re t ur n A p e l l i d o s d e l c o n t a c t o ∗/ public S t r i n g g e t A p e l l i d o s ( ) { return a p e l l i d o s ; } /∗ ∗ ∗ D e v u e l v e e l n´ mero de t e l ´ f o n o d e l c o n t a c t o u e ∗ @re t ur n N´ mero de t e l ´ f o n o d e l c o n t a c t o u e ∗/ public S t r i n g g e t T e l e f o n o ( ) { return t e l e f o n o ; } /∗ ∗ ∗ Cambia e l nombre d e l c o n t a c t o ∗ @param nombre El nuevo nombre d e l c o n t a c t o ∗ @ d e p r e c a t e d E s t e m´ todo s e e l i m i n a r a en v e r s i o n e s f u t u r a s e ´ ∗ @see P e r s o n a ( S t r i n g nombre , S t r i n g a p e l l i d o s , S t r i n g t e l e f o n o ) ∗/ public void setNombre ( S t r i n g nombre ) { t h i s . nombre = nombre ; } /∗ ∗ ∗ Cambia l o s a p e l l i d o s d e l c o n t a c t o ∗ @param a p e l l i d o s Los n u e v o s a p e l l i d o s d e l c o n t a c t o ∗ @ d e p r e c a t e d E s t e m´ todo s e e l i m i n a r a en v e r s i o n e s f u t u r a s e ´ ∗ @see #P e r s o n a ( S t r i n g nombre , S t r i n g a p e l l i d o s , S t r i n g t e l e f o n o ) ∗/ public void s e t A p e l l i d o s ( S t r i n g a p e l l i d o s ) { this . a p e l l i d o s = a p e l l i d o s ; } /∗ ∗ ∗ Cambia e l n´ mero de t e l ´ f o n o d e l c o n t a c t o u e ∗ @param t e l e f o n o El nuevo n´ mero de t e l ´ f o n o u e ∗/ public void s e t T e l e f o n o ( S t r i n g t e l e f o n o ) { this . t e l e f o n o = t e l e f o n o ; } }

del contacto

Listado 2.9: C´digo fuente de la clase Persona con comentarios de o documentaci´n. o El paquete de desarrollo Java nos proporcionan una herramienta para generar la documentaci´n de nuestras clases en formato HTML a partir del c´digo. o o Esta herramienta se llama javadoc. La generaci´n de c´digo se puede realizar o o desde consola de este modo: javadoc Persona.java /ruta/a/directorio Si no se especifica la ruta la documentaci´n se generar´ en el directorio donde o a se encuentre el fichero Persona.java.

48

CAP´ ITULO 2. CLASES

Figura 2.1: javadoc.

Comentarios de documentaci´n generados con la herramienta o

Desde Eclipse tambi´n podemos generar la documentaci´n de nuestras clases e o haciendo click con el bot´n derecho del rat´n sobre el fichero de la clase y despu´s o o e seleccionamos Export → Java Javadoc. Se generar´ toda la documentaci´n de a o nuestra clase, o todo el proyecto si lo hemos seleccionado en vez de una clase individual. En la figura 2.1 se muestra cual es el aspecto de la documentaci´n o generada cuando se utiliza un navegador web para su visualizaci´n. o

Ejercicios.
1. Escribe una clase que abstraiga la idea de Empresa. Una empresa puede tener unicamente como atributos su nombre y un tel´fono de contacto. ´ e 2. A˜ade comentarios de documentaci´n a la clase Empresa y genera la don o cumentaci´n de esta clase. o 3. Escribe un sencillo programa para gestionar los contactos de una agenda telef´nica (clase Agenda). Las operaciones b´sicas que la agenda telef´nica o a o es capaz de realizar son:

´ 2.9. COMENTARIOS. COMENTARIOS DE DOCUMENTACION. a) Insertar nuevas Personas en la agenda. b) Listar todas las Personas de la agenda. c) Buscar una Persona a partir de su nombre.

49

Lecturas recomendadas.
El excelente libro de Arnold y otros [2] es una referencia completa a la definici´n de clases. Comenta de modo exhaustivo todos los detalles en la o definici´n de una clase, los distintos modificadores de acceso y su signifio cado. El modo de presentar los conceptos del lenguaje Java ne la serie de libros de la colecci´n Head first Java es muy interesante. En particular, la referencia o [3] presenta de una manera muy visual los principales conceptos en la definici´n de clases en Java. o Finalmente, una lectura siempre recomendable sobre buenas pr´cticas y a escritura de c´digo limpia es el libro de Robert C. Martin de la referencia o [10].

50

CAP´ ITULO 2. CLASES

2. . . . . . . . La palabra reservada super. .2. . .2. . 3. . . . Enumeraciones. . . . . . . . . . .Cap´ ıtulo 3 Herencia e Interfaces Contenidos 3. 3. 3. . . . . . . Clases abstractas. . . . . atributos y m´todos. . . . . . . . . . . . . La Herencia nos permite construir una clase a˜adienn 51 . . . . 3. . . . . Interfaces. . . . . o n ¿C´mo puedo ampliar el conjunto de m´todos que proporciona? o e En POO existe un mecanismo fundamental para a˜adir funcionalidad a una n clase el concepto es la Herencia. . . 3. . ¿Qu´ ocurre si quiero a˜adir m´s funcionalidad e n a a mis clases?. .2. 52 52 54 56 59 59 60 61 62 63 65 68 69 71 . tambi´n conocido como Extensi´n o Derivaci´n. . 3. .1. . . Sobrescribir atributos. . . . . . . 3. . Extensi´n de una clase. El operador instanceof. . . . . . . . . .2. . . . .5. . . . . . . . e 3. . . . .3. . .6. .4.4. . . . . .2. Sobrescribir m´todos. Introducci´n o En el cap´ ıtulo 2 hemos visto c´mo podemos codificar la abstracci´n de una o o entidad del mundo real a c´digo Java. . . . . . . . . . adem´s de algunos de los modificadores o e a que podemos utilizar sobre ellos. . Tambi´n hemos aprendido a crean instancias e a partir de una clase con el operador new. .6. . . . . . .2. . .3. . . . . . . . . . . . . . . . . 3. . . . . . . . . . . 3. . . Paquetes en Java. . . . El constructor por defecto y la clase Object.7. . . . . . . o 3. . . . . e o o La idea b´sica de la Herencia es crear una nueva clase a partir de la definici´n a o de otra clase ya existente. . . .1. . . El modificador final. . . . .2. . . . . . . . . . . . Clases e interface anidados . . . . . . . . . . Hemos visto la sintaxis de Java para la o creaci´n de clases. . . . . . .2. . . . . La situaci´n en la que nos encontramos ahora es que nuestras clases abstraen o entidades del mundo real pero. Herencia. . . . . . .7. . . . M´todos static.5. . . . . . . . . . . . . . . . . . ¿C´mo puedo a˜adir nuevos atributos a una clase ya existente?. . . . . 3. . . e 3. . . . .

para a˜adirle n nueva funcionalidad. a la clase original se le llama clase padre o base. HERENCIA E INTERFACES do unicamente la nueva funcionalidad a otra clase ya existente. una clase hija no puede tener m´s de una clase padre. con o lo aprendido hasta ahora podemos resolverlo. En esta secci´n vamos a ver c´mo se puede ampliar el comportamiento de o o una clase a trav´s de la herencia. a Caracter´ ıstica Java s´lo admite herencia simple. e 3. o e 3. Veremos tambi´n el concepto. Y tambi´n nos ´ e permite modificar el comportamiento de la clase original sobrescribiendo sus m´todos.52 CAP´ ITULO 3. muy importante. Para o ello tenemos dos alternativas antag´nicas: o 1. Para indicar que una clase extiende el comportamiento de otra utilizamos la palabra reservada extends. y llamemos a esta nueva clase Ciudadano. en Java lo hacemos e de este modo: 1 Cuando veamos las clases para manipular fechas en el Cap´ ıtulo 8 veremos una mejor implementaci´n para obtener la edad de una persona a partir de su fecha de nacimiento o . En Java se dice que una clase extiende a otra clase cuando a˜ade m´s funn a cionalidad a una clase ya existente. Si optamos por la segunda opci´n estaremos haciendo uso del mecanismo de o Herencia. Veamos como se utiliza este mecanismo y cual es su sintaxis en Java. o Lo primero que hay que destacar es que en Java s´lo est´ permitida la herencia o a simple. Dicho de o ´ otro modo. Imaginemos que necesitamos ampliar nuestra clase Persona. Aprovechar al m´ximo el c´digo existente. ı Finalmente veremos el significado de los modificadores final y abstract cuando se aplican a la definici´n de un m´todo o una clase. Una clase no puede tener m´s de una clase o a padre. como son la Provincia y la Poblaci´n o y tambi´n la Edad. Herencia. la poblaci´n de residencia y la edad 1 de cada uno de nuestros contactos. a o Si optamos por la primera opci´n. 2. Reescribir la clase desde cero. A la nueva clase se le llama clase hija o extendida. Extensi´n de una clase. e e de la vinculaci´n din´mica para encontrar qu´ m´todo se ha de invocar al utio a e e lizar referencias a clases extendidas.2. no tenemos nada nuevo que aprender.1. Queremos que nuestra nueva clase contenga la provincia. Supongamos que queremos ampliar la definici´n de una Persona para que o contenga datos de su lugar de residencia. una nueva clase s´lo puede extender a una unica clase base. as´ como el uso del operador instanceof.

" Madrid " . o System . o En el Listado 3. } public void setEdad ( i n t edad ) { t h i s . 53 1 2 3 public c l a s s Ciudadano extends P e r s o n a { // D e f i n i c i ´ n de l a nueva c l a s e e x t e n d i d a o } En la definici´n de la nueva clase podemos incluir nuevos atributos y m´too e dos. 40. } public S t r i n g g e t P o b l a c i o n ( ) { return p o b l a c i o n . public c l a s s Ciudadano extends P e r s o n a { private S t r i n g p o b l a c i o n . " 5 5 5 1 2 3 4 5 6 " .´ 3. poblacion = poblacion . como en el siguiente a e ejemplo de c´digo: o 1 2 Ciudadano c i u d a d a n o = new Ciudadano ( " J o s e " . o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package t i p o s . o u t . getNombre ( ) ) . tanto de los definidos en o e la clase extendida como los definidos en la clase base?. . EXTENSION DE UNA CLASE. provincia = provincia . edad = 0 . edad = edad . } } () { Listado 3. iniciaAtributos () . sencillamente como lo est´bamos haciendo hasta ahora: a trav´s de las referencias.6.1: Definici´n de la clase Ciudadano o ¿C´mo hacemos uso de los m´todos de la clase. public Ciudadano ( ) { super ( ) . private S t r i n g p r o v i n c i a . } public void s e t P r o v i n c i a ( S t r i n g p r o v i n c i a ) { this . } public S t r i n g g e t P r o v i n c i a ( ) { return p r o v i n c i a . private i n t edad .1 aparece la definici´n completa de la nueva clase Ciudadano. } public i n t getEdad ( ) { return edad . En el siguiente c´digo de ejemplo. Nuestra nueva clase Ciudadano posee tanto los nuevos m´todos defie nidos en ella como los m´todos definidos en su clase padre (con las restricciones e de accesibilidad que veremos en la secci´n 3. p r i n t l n ( " N o m b r e : " + c i u d a d a n o . " ´ ´ Alcorc´n " . } public void s e t P o b l a c i o n ( S t r i n g p o b l a c i o n ) { this . a la clase Ciudadano se le han a˜adido los o n tres nuevos atributos antes mencionados y los getters y setters para estos nuevos atributos.2. " G a r c ı a " . } @Override protected void i n i c i a A t r i b u t o s setNombre ( " U n n o m b r e " ) .

y a trav´s de la e referencia a Ciudadano podr´ ıamos invocar a. // P e r f e c t a m e n t e v a l i d o . podr´ e ıa o ıamos asignar a una referencia a Ciudadano una referencia de su clase padre Persona. getNombre ( ) e s t a d e f i n i d o en ´ Persona . Sobrescribir atributos. a partir de una referencia de la clase hija. p r i n t l n ( " E d a d : " + c i u d a d a n o . el siguiente c´digo de ejemplo contiene un error: o 1 2 P e r s o n a p e r s o n a = new P e r s o n a ( ) . como muestra el siguiente c´digo de ejemplo: o 1 2 3 4 5 6 7 8 9 10 11 12 // Est a e s l a c l a s e p a d r e public c l a s s D i s t a n c i a { float distancia . public D i s t a n c i a ( ) { distancia = 0. o u t . p e r s o n a . Pesona p e r s o n a = c i u d a d a n o . o para el ejemplo de la clase padre Persona y su clase hija Ciudadano. ´ p e r s o n a . // E r r o r ! ! ! Concepto clave Una referencia de una clase padre admite una referencia a cualquiera de sus clase hijas. e pero. } // S i g u e l a d e f i n i c i ´ n de e s t a c l a s e . pero nunca al contrario. Como vemos en la l´ ınea 2 del Listado anterior. aunque es perfectamente v´lido asignar una referencia de una e a clase hija a una referencia a la clase padre. getNombre ( ) . getEdad ( ) .2.1. d i s t a n c i a = d i s t a n c i a . } public D i s t a n c i a ( f l o a t d i s t a n c i a ) { this . HERENCIA E INTERFACES System . hacemos uso del m´todo e getNombre() definido en la clase padre. En algunas circunstancias. podemos vernos en la necesidad de definir un atributo en una clase hija con el mismo nombre que en su clase padre. En particular. a Tambi´n es un error asignar a una referencia de una clase hija una referencia e a la clase padre.54 3 CAP´ ITULO 3. getEdad ( ) e s t ´ d e f i n i d o en Ciudadano . el m´todo getEdad().. getEdad ( ) ) . ¿Podemos utilizar una referencia a la clase padre para acceder a los mismos m´todos? No. Piensa qu´ ocurrir´ si no existiese esta prohibici´n. // E r r o r ! ! ! . a trav´s de la referencia a la clase e padre s´lo tendremos acceso a los miembros declarados en ella. por ejemplo. mientras que en la l´ ınea 3 hacemos uso del m´todo getEdad() definido en e la clase hija. la clase Persona no posee el atributo int edad. el siguiente c´digo ejemplo contiene un error: o 1 2 3 4 Ciudadano c i u d a d a n o = new Ciudadano ( ) . ¿Qu´ se deber´ devolver e ıa en este caso? 3. // No hay problema . o . Ciudadano c i u d a d a n o = p e r s o n a .

o ¿C´mo accedemos al atributo distancia desde fuera de la clase? Ya lo sabeo mos.´ 3. distancia ) . a trav´s de referencias. ¿Qu´ mostrar´ el siguiente e e a ejemplo?: 1 2 3 4 D i s t a n c i a d i s t a n c i a = new D i s t a n c i a ( 1 0 0 ) . que en los dos casos es Distancia y el atributo que se est´ iniciando en la l´ a ınea 3 del c´digo anterior es el de la clase hija o DistanciaDoblePrecision pues el objeto que se crea es de la clase extendida. p r i n t l n ( " E l v a l o r d e d i s t a n c i a D o b l e P r e c i s i o n e s : " + distanciaDoblePrecision . De acuerdo. de modo que si aparece el nombre del atributo en la clase hija se utilizar´ el atributo definido en esta clase a y no el definido en la clase padre. distancia ) .0 . Comparemos con el resultado de la ejecuci´n de este otro c´digo ejemplo: o o 1 2 3 4 D i s t a n c i a d i s t a n c i a = new D i s t a n c i a ( 1 0 0 ) . public D i s t a n c i a D o b l e P r e c i s i o n ( ) { distancia = 0.0 El valor de distancia2 es: 0. System . D i s t a n c i a d i s t a n c i a D o b l e P r e c i s i o n = new D i s t a n c i a D o b l e P r e c i s i o n ( 2 0 0 ) . System .0 ¿Qu´ ha ocurrido? Nada extra˜o. Lo que mostrar´ este c´digo es. d i s t a n c i a ) . 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 55 } // Esta e s l a c l a s e h i j a public c l a s s D i s t a n c i a D o b l e P r e c i s i o n extends D i s t a n c i a { // E s t e e s e l a t r i b u t o s o b r e s c r i t o double d i s t a n c i a . o } En este caso se dice que el atributo distancia de la clase hija DistanciaDoblePrecision sobrescribe el atributo distancia de la clase padre Distancia. System . } // S i g u e l a d e f i n i c i ´ n de e s t a c l a s e . System .2. Esto no quiere decir que el atributo con el mismo nombre en la clase padre desaparezca. sino que para acceder a ´l tene dremos que hacer uso de otro mecanismo como veremos m´s adelante en esta a secci´n. d i s t a n c i a = d i s t a n c i a . o u t . Cuando una clase hija sobrescribe alg´n atributo de su clase u padre. o u t . d i s t a n c i a ) . Lo que mostrar´ este c´digo es: a o El valor de distancia es: 100. el atributo de la clase padre queda oculto . p r i n t l n ( " E l v a l o r d e d i s t a n c i a D o b l e P r e c i s i o n e s : " + distanciaDoblePrecision . EXTENSION DE UNA CLASE. sorpresa: a o El valor de distancia es: 100. D i s t a n c i a D o b l e P r e c i s i o n d i s t a n c i a D o b l e P r e c i s i o n = new DistanciaDoblePrecision (200) . se ha buscado este valor en la definici´n de la clase e o correspondiente a la referencia. o u t . p r i n t l n ( " E l v a l o r d e d i s t a n c i a e s : " + d i s t a n c i a .0 El valor de distanciaDoblePrecision es: 200. entonces. p r i n t l n ( " E l v a l o r d e d i s t a n c i a e s : " + d i s t a n c i a . } public D i s t a n c i a D o b l e P r e c i s i o n ( double d i s t a n c i a ) { this . simplemente que al acceder al atributo e n a trav´s de la referencia. o u t .

System . p r i n t l n ( " E l v a l o r d e d i s t a n c i a e s : " + d i s t a n c i a . Sobrescribir m´todos. e Para introducir el modo de sobrescribir m´todos imaginemos que hemos a˜adido e n al c´digo de la clase Distancia un nuevo m´todo que nos permita incrementar o e la distancia actual: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public c l a s s D i s t a n c i a { float distancia . public D i s t a n c i a D o b l e P r e c i s i o n ( ) { distancia = 0.2.0 ¿C´mo es posible? Estamos intentando incrementar la distancia inicial de o 100 en otros 100. lo unico que ha cambiado es el tipo de ´ ´ la referencia distanciaDoblePrecision. y este m´todo incrementa el valor del atributo que hay definido en e ella. } void i n c r e m e n t a D i s t a n c i a ( f l o a t i n c r e m e n t o ) { d i s t a n c i a += i n c r e m e n t o . a Nuestro nuevo m´todo incrementaDistancia(float) est´ definido en la e a clase padre.2: Definici´n de la clase Distancia o Ahora queremos probar nuestra nueva funcionalidad con este ejemplo: 1 2 3 D i s t a n c i a D o b l e P r e c i s i o n d i s t a n c i a = new D i s t a n c i a D o b l e P r e c i s i o n ( 1 0 0 ) . incrementaDistancia (100) . es decir. distancia . ¿Donde est´ el problema?. ¿C´mo podemos arreglarlo? La respuesta es sobrescrio biendo el m´todo incrementaDistancia(float) en la clase hija de este modo: e 1 2 3 4 5 6 7 public c l a s s D i s t a n c i a D o b l e P r e c i s i o n extends D i s t a n c i a { double d i s t a n c i a . el atributo seleccionado se determina por el tipo de la referencia.2. y parece que no lo conseguimos.56 CAP´ ITULO 3. d i s t a n c i a = d i s t a n c i a . HERENCIA E INTERFACES En este ultimo ejemplo. la clase hija. no en la clase hija. d i s t a n c i a ) . o u t . que en este caso es de tipo DistanciaDoblePrecision. o } Listado 3. Concepto clave Cuando una clase hija sobrescribe (oculta) un atributo de la clase padre. } // S i g u e l a d e f i n i c i ´ n de e s t a c l a s e . public D i s t a n c i a ( ) { distancia = 0. } . 3. El resultado que obtenemos es el siguiente: El valor de distancia es: 100. } public D i s t a n c i a ( f l o a t d i s t a n c i a ) { this .

2.0 Para que una clase hija sobrescriba un m´todo de su clase padre es necesario e que ambos m´todos tengan la misma signatura y el mismo tipo de retorno. 2 Las anotaciones fueron introducidas en la versi´n 5 de Java o . o } Aunque es posible que la clase hija sobrescriba un m´todo de la clase pae dre ampliando el modificador de acceso. } // S i g u e l a d e f i n i c i ´ n de e s t a c l a s e . en el caso del Listado 3. El valor de distancia es: 200. ıa Gracias al uso de la anotaci´n @Override2 obtenemos un error que nos o informa que el nuevo m´todo no est´ sobrescribiendo a ning´n m´todo en su e a u e clase padre. } @Override void i n c r e m e n t a D i s t a n c i a ( f l o a t i n c r e m e n t o ) { d i s t a n c i a += i n c r e m e n t o . a e Ahora s´ el resultado obtenido es: ı. } public D i s t a n c i a D o b l e P r e c i s i o n ( double d i s t a n c i a ) { this . EXTENSION DE UNA CLASE. el hijo restrinja e el modificador de acceso.´ 3. de e lo contrario no se sobrescribe el m´todo. de modo que hemos ampliado el modificador de acceso desde acceso paquete hasta public. Lo que no est´ pera mitido es que cuando se sobrescribe un m´todo de la clase padre. d i s t a n c i a = d i s t a n c i a . o } Listado 3. Si eliminamos la anotaci´n no obtenemos ning´n error y lo que o u estaremos haciendo es definiendo un nuevo m´todo que toma como argumento e una variable de tipo double. como en el siguiente ejemplo: e 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public c l a s s D i s t a n c i a D o b l e P r e c i s i o n extends D i s t a n c i a { double d i s t a n c i a .3: Definici´n de la clase DistanciaDoblePrecisiona o N´tese el uso de la anotaci´n @Override que indica al compilador de Java que o o se est´ intentando sobrescribir un m´todo en la clase padre. dar´ un error.2. public D i s t a n c i a D o b l e P r e c i s i o n ( ) { distancia = 0. Siguiendo con el ejemplo. } // S i g u e l a d e f i n i c i ´ n de e s t a c l a s e . d i s t a n c i a = d i s t a n c i a . intentar sobrescribir el m´toe do incrementaDistancia como private void incrementaDistancia(double incremento). por ejemplo. 8 9 10 11 12 13 14 15 16 17 57 public D i s t a n c i a D o b l e P r e c i s i o n ( double d i s t a n c i a ) { this . } // I n t e n t a m o s s o b r e s c r i b i r cambiando e l t i p o d e l argumento // Se p r o d u c e un e r r o r @Override void i n c r e m e n t a D i s t a n c i a ( double i n c r e m e n t o ) { d i s t a n c i a += i n c r e m e n t o .2 posemos definir el m´todo incrementaDistancia como public void e incrementaDistancia(double incremento).

incrementaDistancia(100) fue el que increment´ la vinculaci´n o o din´mica. Este concepto es muy importante en POO y a este mecanismo se le llama Vinculaci´n din´mica . ¿Qu´ es lo que obtenemos? Sorpresa de nuevo: e El valor de distancia es: 0. o u t . de acuerdo. es decir.distancia estamos accediendo al atributo en Distancia pero el atributo que se increment´ con o distancia. HERENCIA E INTERFACES Buenas pr´cticas a Para asegurar que los m´todos en las clases hijas sobrescriben m´todos en la e e clase padre util´ ıcese la anotaci´n @Override en el m´todo sobrescrito.2. pero el tipo del objeto al que hace referencia. La respuesta. o a ¿Qu´ est´ ocurriendo entonces? Ocurre que distancia es una referene a cia de tipo Distancia. incrementaDistancia (100) . el de DistanciaDoblePrecision. Mientras que o tal y como sabemos de la Secci´n 3. System . a N´tese la diferencia fundamental con respecto al acceso a los atributos.1. el que creamos con el operador new es DistanciaDoblePrecision. donde o el atributo al que se accede se determina por el tipo de la referencia y no del objeto. por lo tanto si escribimos distancia.0 si estamos creando un objeto de tipo o DistanciaDoblePrecision con un valor inicial de 100 y despu´s lo estamos e incrementando en 100 unidades m´s?. distancia . si utilizamos atributos no se o hace uso de la vinculaci´n din´mica y se accede al atributo correspono a diente al tipo que indica la referencia no el objeto que hay por debajo de ella.0 ¿C´mo puede ser que obtengamos 0. Al usar el m´todo incrementaDistancia(100) la vinculaci´n din´mica ejecuta el e o a c´digo de DistanciaDoblePrecision no el de Distancia. modifiquemos nuestro c´digo de o prueba del siguiente modo: 1 2 3 D i s t a n c i a d i s t a n c i a = new D i s t a n c i a D o b l e P r e c i s i o n ( 1 0 0 ) . p r i n t l n ( " E l v a l o r d e d i s t a n c i a e s : " + d i s t a n c i a . o e Ya sabemos que a una referencia a una clase padre le podemos asignar una referencia a cualquier clase hija. esta vez est´ recogida en a a este concepto clave: Concepto clave Cuando accedemos a los m´todos de un objeto a trav´s de una referencia se e e selecciona el m´todo a partir del tipo del objeto y no de la referencia a trav´s e e de la que se accede.58 CAP´ ITULO 3. ya que se ha ampliado el tipo del valor de retorno . d i s t a n c i a ) . Tambi´n es posible que una clase sobrescriba un m´todo ampliando el tipo e e del valor de retorno. es decir que si en la clase padre Distancia tenemos un m´todo como Distancia metodo() la clase hija puede sobrescribirlo con el m´todo e e DistanciaDoblePrecision metodo().

si ´ tenemos en la clase padre un m´todo definido como public float unMetodo() e que devuelve el tipo primitivo float no lo podemos sobrescribir en una clase hija con public double unMetodo() que devuelve el tipo primitivo double.´ 3. 3.2) ni de la clase a e DistanciaDoblePrecision (v´ase el listado 3. Existen casos en los que.3).2. esto ultimo no funciona con los tipos de retorno primitivos. ¿C´mo accedemos a los miembros o o sobrescritos desde la clase hija?. En el c´digo de los ejemplos de prueba. EXTENSION DE UNA CLASE. nos interesa acceder a los m´todos o atributos sobrescritos en la clase padre.2. esta posibilidad fue introducida en la versi´n 5 de Java. desde una clase hija.4. del mismo modo que la palabra reservada this es una referencia a la propia clase. } // S i g u e l a d e f i n i c i ´ n de e s t a c l a s e . La respuesta es haciendo uso de la palabra reservada super. // E l i m i n a d o e l constructor s i n parametros ´ public D i s t a n c i a D o b l e P r e c i s i o n ( double d i s t a n c i a ) { this . podemos intentar elie minar estos dos constructores e iniciar el atributo distancia de ambas clases en el momento de la definici´n.3. 59 desde el original Distancia a DistanciaDoblePrecision. luego. } // S i g u e l a d e f i n i c i ´ n de e s t a c l a s e . nunca hemos utilizado el construco tor sin par´metros de las clases Distancia (v´ase el listado 3. } @Override void i n c r e m e n t a D i s t a n c i a ( f l o a t i n c r e m e n t o ) { d i s t a n c i a += i n c r e m e n t o . // E l i m i n a d o e l constructor D i s t a n c i a −−−−// s i n parametros ´ public D i s t a n c i a ( f l o a t d i s t a n c i a ) { this . tal y como se muestra en el siguiente listado: o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 //−−−− D e f i n i c i ´ n de l a c l a s e o public c l a s s D i s t a n c i a { float distancia = 0. } void i n c r e m e n t a D i s t a n c i a ( f l o a t i n c r e m e n t o ) { d i s t a n c i a += i n c r e m e n t o . o } //−−−− D e f i n i c i ´ n de l a c l a s e D i s t a n c i a D o b l e P r e c i s i o n −−−−// o public c l a s s D i s t a n c i a D o b l e P r e c i s i o n extends D i s t a n c i a { double d i s t a n c i a = 0 . 3. o . Definici´n o La palabra reservada super es una referencia a la clase padre. o Pero cuidado. El constructor por defecto y la clase Object. d i s t a n c i a = d i s t a n c i a . d i s t a n c i a = d i s t a n c i a . La palabra reservada super. Si escribimos en la clase hija e simplemente el nombre del atributo o del m´todo estaremos haciendo uso de e la definici´n dada para ellos en la clase hija.2.

bien directamente o bien a trav´s de herencia. lo primero que se hace desde el constructor de una clase hija es llamar al constructor por defecto de la clase padre. el constructor de la clase hija public DistanciaDoblePrecision(double distancia) est´ intentando invocar impl´ a ıcitamente al constructor de la clase padre public Distancia() que no est´ definido.2. Must explicitly invoke another constructor. d i s t a n c i a = d i s t a n c i a . HERENCIA E INTERFACES Pero inmediatamente obtendremos el siguiente error en el c´digo de la clase o DistanciaDoblePrecision Implicit super constructor Distancia() is undefined. se intenta invocar al constructor sin par´metros de la clase padre. El operador instanceof. // Llamamos a l c o n s t r u c t o r con p a r ´ m e t r o s d e l p a d r e a this . Buenas pr´cticas a Para evitar problemas en la ceraci´n de objetos. la llamada al constructor del padre es o lo primero que debemos hacer en el construtor del hijo.2? Para responder a esta pregunta necesitamos saber que la clase Object es la clase que est´ en la ra´ del ´rbol a ız a de jerarqu´ de clases en Java. a˜adiendo los construcn tores por defecto a cada una de las clases. desde los constructores o de las clases hijas. si no se indica lo contrario. El error anterior lo podemos corregir de dos modos. es hija de e la clase Object. Este error es debido a que.60 CAP´ ITULO 3. o bien. llamando desde el constructor con par´metros de la clase hija al constructor con par´metros de la clase paa a dre. que por este motivo es llamado Constructor por a defecto . que no a est´ definido: a 1 2 3 4 public D i s t a n c i a D o b l e P r e c i s i o n ( f l o a t d i s t a n c i a ) { super ( 0 ) . y que si una clase expl´ ı ıcitamente no extiende a ninguna otra. Ya sabemos que cuando llamamos a los m´todos de un objeto a trav´s de una e e referencia.5. es el tipo del objeto (la clase a la que pertenece) el que determina qu´ m´todo se ha de llamar. } Si optamos por la segunda soluci´n. en el ejemplo anterior si intercambiamos las l´ ıneas 3 y 4 obtendremos el siguiente error Constructor call must be the first statement in a constructor La pregunta que nos surge es ¿A qu´ constructor se llama desde el construce tor por defecto de la clase Distancia que no est´ extendiendo a ninguna otra a clase. 3. Si no se indica lo contrario. impl´ ıcitamente est´ extendiendo a la clase Object. es conveniente definir siempre o el constructor por defecto en nuestras clases. A este mecanismo lo hemos llamado Vinculaci´n e e o . tal y como se muestra en el Listado 3. ız a ıa Cualquier otra clase. a Concepto clave La clase Object se encuentra en la ra´ del ´rbol de jerarqu´ de clases en Java. Este es el mecanismo en la creaci´n de objetos a o en Java cuando existe relaci´n de herencia entre clases. para que no se llame por defecto el constructor sin par´metros.

// D e v o l v e r a \emph{ ´ false} Ciudadano c i u d a d a n o = new Ciudadano ( ) . Para dar contestaci´n a esta pregunta Java pone a nuestra disposici´n un o o operador binario. o u t . p r i n t l n ( p e r s o n a i n s t a n c e o f P e r s o n a ) . utiliza polimorfismo o para no hacer uso de este operator. No importa el tipo de la referencia a la que asignemos el objeto siema pre que. p r i n t l n ( p e r s o n a i n s t a n c e o f Ciudadano ) . e e de tal modo que si un m´todo se declara como final estamos indicando que e ese m´todo no puede ser sobrescrito por ninguna clase hija. conviene seguir la siguiente buena pr´ctica: a Buenas pr´cticas a Intenta evitar el uso del operador instanceof en tu c´digo. // D e v o l v e r a \emph{ ´ true } Aunque el operador instanceof nos puede prestar ayuda en algunos casos. System . ¿C´mo o podemos conocer el verdadero tipo del objeto asignado a la referencia?. el operador instanceof con el que podemos preguntar si el objeto asignado a una referencia es de un determinado tipo o no. el tipo de la referencia sea compatible con el tipo del objeto. En el siguiente listado se muestra c´mo o se puede violar el comportamiento al iniciar una instancia por parte de un hijo si el padre no protege el m´todo que inicia los atributos con el modificado final e : 1 2 3 4 5 6 7 8 // C´ digo de l a c l a s e p a d r e o public c l a s s P e r s o n a { private S t r i n g nombre . private S t r i n g t e l e f o n o . en tiempo de ejecuci´n el mecanismo de vinculaci´n din´mica determio o a nar´ cual es el m´todo que se ha de llamar si es que ese m´todo est´ sobrescrito. 3. 61 din´mica. EXTENSION DE UNA CLASE. El operador final tambi´n se puede aplicar a los m´todos de una clase. En el cap´ ıtulo 2 vimos el uso del modificador final aplicado a los atributos de una clase. // D e v o l v e r a \emph{ ´ true } System . // D e v o l v e r a \emph{ t r u e } ´ System . Estos son algunos casos de uso: 1 2 3 4 5 6 P e r s o n a p e r s o n a = new P e r s o n a ( ) . El modificador final. basta con que sean compatibles. Con ello estamos e garantizando que el trabajo que realiza el m´todo es siempre el mismo con e independencia de si el objeto sobre el que se llama es instancia de la clase padre o instancia de alguna de sus clases hijas. p r i n t l n ( c i u d a d a n o i n s t a n c e o f Ciudadano ) . private s t a t i c i n t n I n s t a n c i a s . p r i n t l n ( c i u d a d a n o i n s t a n c e o f P e r s o n a ) . el valor de retorno de este operador es un booleano true o false. private S t r i n g a p e l l i d o s . o u t .´ 3. System . public P e r s o n a ( ) { . o u t .2. evidentemente. a e e a La pregunta que ahora nos surge es: Si el unico acceso que tenemos es a ´ trav´s de referencias y el tipo de la referencia no tiene por qu´ coincidir con e e el tipo del objeto que tiene asignado.2. o u t .6.

62
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

CAP´ ITULO 3. HERENCIA E INTERFACES

super ( ) ; iniciaAtributos () ; } protected void i n i c i a A t r i b u t o s ( ) { nombre = " " ; apellidos = "" ; telefono = "" ; nInstancias = 0; } // S i g u e l a d e f i n i c i ´ n de l a c l a s e o // C´ digo de l a c l a s e h i j a o public Ciudadano ( ) { super ( ) ; // Aqu´ cambiamos e l comportamiento de i n i c i o de l o s ı iniciaAtributos () ; } @Override protected void i n i c i a A t r i b u t o s ( ) { setNombre ( " U n n o m b r e " ) ; } // S i g u e l a d e f i n i c i ´ n de l a c l a s e o

atributos

Simplemente a˜adiendo el modificador final al m´todo iniciaAtributos n e de la clase padre, si intentamos sobrescribir este m´todo en la clase hija obe tendremos el siguiente error Cannot override the final method from Persona advirti´ndonos que no podemos sobrescribir un m´todo declarado como final e e en la clase padre. Buenas pr´cticas a Los m´todos a los que se llama desde los constructores de una clase deben e ser modificados como final para prevenir que alguna clase hija modifique el comportamiento al crear instancias de la clase. Es muy recomendable seguir la anterior buena pr´ctica, piensa que ocurrir´ a ıa si en el constructor de una clase padre que abre una conexi´n a una base de o datos, y una clase hija sobrescribiese las tareas de inicio, y la conexi´n a la base o de datos no se estableciese; toda la aplicaci´n dejar´ de funcionar. o ıa El modificador final tambi´n se puede aplicar sobre una clase de este modo: e
1 2

public f i n a l c l a s s P e r s o n a { // La d e f i n i c i o n de l a c l a s e ´

En este caso lo que estamos indicando es que la clase Persona no se puede extender porque la hemos declarado como final. Un ejemplo de clase final en Java es la clase String que est´ declarada como final y por lo tanto no se a puede extender, es decir no podemos crear hijas de ella.

3.2.7.

M´todos static. e

En el Cap´ ıtulo 2 vimos el significado del modificador static cuando se aplica a m´todos. El modificador static indica que el m´todo pertenece a la e e clase y no a las instancias de la clase. Por otro lado hemos visto lo que significa la Vinculaci´n din´mica, determinar en tiempo de ejecuci´n el m´todo que se o a o e debe llamar al invocarse desde una instancia cuando est´ sobrescrito. F´ a ıjate

3.3. CLASES ABSTRACTAS.

63

que el mecanismo de sobrescribir m´todos funciona en el ´mbito de los objetos, e a mientras que los m´todos static pertenecen al ´mbito de las clases. Es por esto e a que un m´todo static de una clase padre no se puede sobrescribir, los m´todos e e static de la clase padre son m´todos ocultos que no son visibles desde las clases e hija. Si en una clase hija declaramos un m´todo con la misma signatura que un e m´todo static en la clase padre, lo que estamos haciendo realmente es creando e un nuevo m´todo en la clase hija sin ninguna relaci´n con el mismo m´todo e o e en la clase padre. Obviamente si intentamos usar la anotaci´n @Override para o indicar que queremos sobrescribir el m´todo obtendremos un error This instance e method cannot override the static method from ...

3.3.

Clases abstractas.

Hasta este momento, siempre que hemos definido los m´todos de las clases que e hemos creado, siempre hemos escrito c´digo en la definici´n de los m´todos. A o o e veces es util simplemente declarar m´todos un una clase padre, sin dar ninguna ´ e implementaci´n para ellos, y delegar la implementaci´n a las clases hijas que o o la extiendan. Esta es una t´cnica muy potente que utiliza el concepto de Polie morfismo de la POO. De este modo estamos garantizando que todas las clases hijas de la misma clase padre tiene un m´todo con la misma signatura, aunque, e obviamente, cada una de las clase hijas puede tener una implementaci´n distinta o para el m´todo polim´rfico. e o Si queremos indicar que no vamos a dar una implementeaci´n para alg´n o u m´todo declarado en la clase, debemos modificarlo con la palabra reservada e abstract, con la restricci´n de que si una clase tiene alg´n m´todo abstract o u e ella misma tambi´n debe ser declarada como abstract. e Tambi´n podemos declarar una clase como abstract sin que ninguno de sus e m´todos los sea. Si una clase es declarada como abstract, sobre ella tenemos e la restricci´n recogida en el siguiente concepto clave: o Concepto clave No se pueden crear instancias de una clase declarada como abstract De no existir esta restricci´n ¿Qu´ ocurrir´ si se llamase a un m´todo o e ıa e abstract de un objeto? ¿Qu´ c´digo se ejecutar´ Evidentemente de poder e o ıa? ser as´ tendr´ ı ıamos un grave problema, ya que puede que no existiene ning´n u c´digo para ejecutar. o Los m´todos abstract de la clase padre deben ser definidos en las clases e hijas, en cuyo caso los m´todos en las clase hijas ya no ser´n abstract y tampoco e a la propia clase hija. Ahora bien, puede existir alg´n el caso en que una clase hija u tampoco defina alg´n m´todo abstract de la clase padre; en este caso la clase u e hija tambi´n deber´ ser declarada abstract y no podremos crear instancias de e a ella. Un ejemplo recurrente para mostrar el uso de las clases abstract es una aplicaci´n que dibuje distintas figuras geom´tricas tales como c´ o e ırculos, tri´ngulos a y cuadrados. Podr´ ıamos declara el comportamiento com´n de todas estas clases, u por ejemplo el m´todo dibujate() en una clase padre llamada Figuras, y e cada una de las clases hijas tuviese la implementaci´n adecuada para dibujarse o

64

CAP´ ITULO 3. HERENCIA E INTERFACES

dependiendo de su naturaleza. De modo muy esquem´tico el c´digo de estas a o clases podr´ ser algo como lo mostrado en el Listado 3.4: ıa
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

public abstract c l a s s F i g u r a { public abstract void d i b u j a t e ( ) ; // S i g u e l a d e f i n i c i ´ n de l a c l a s e o } public c l a s s T r i a n g u l o extends F i g u r a { public void d i b u j a t e ( ) { // C´ digo p a r a d i b u j a r un t r i ´ n g u l o o a } // S i g u e l a d e f i n i c i ´ n de l a c l a s e o } public c l a s s Cuadrado extends F i g u r a { public void d i b u j a t e ( ) { // C´ digo p a r a d i b u j a r un c u a d r a d o o } // S i g u e l a d e f i n i c i ´ n de l a c l a s e o } public c l a s s C i r c u l o extends F i g u r a { public void d i b u j a t e ( ) { // C´ digo p a r a d i b u j a r un c´ r c u l o o ı } // S i g u e l a d e f i n i c i ´ n de l a c l a s e o }

Listado 3.4: Definici´n de una clase abstract y algunas clases hijas. o La potencia del c´digo del Listado anterior se hace evidente cuando recoro damos que podemos asignar cualquier objeto de una clase hija (Triangulo, Cuadrado o Circulo) a una referencia de la clase padre Figura, de modo que podr´ ıamos escribir algo como:
1 2 3 4 5 6

F i g u r a f i g u r a = new C i r c u l o ( ) ; f i g u r a . d i b u j a t e ( ) ; // D i b u j a r a un c´ r c u l o ´ ı f i g u r a = new T r i a n g u l o ( ) ; f i g u r a . d i b u j a t e ( ) ; // D i b u j a r a un t r i a n g u l o ´ ´ f i g u r a = new Cuadrado ( ) ; f i g u r a . d i b u j a t e ( ) ; // D i b u j a r a un c u a d r a d o ´

Listado 3.5: Uso de una referencia a una clase padre abstract para recorrer instancias de las clases hijas. De nuevo la Vinculaci´n din´mica en cada una de las llamadas al m´todo o a e dibujate() determinar´ el m´todo que se debe invocar. a e

Buenas pr´cticas a El dise˜o de tus aplicaciones debe estar orientado al interface no a la implemenn taci´n. o ¿Qu´ quiere decir esta buena pr´ctica? La idea es que debes concentrarte en e a crear buenas abstracciones, es decir debes intentar encontrar el comportamiento com´n (declaraci´n de los m´todos) a tus clases para que las puedas tratar de u o e manera homog´nea, con independencia de c´mo se materializa ese comportae o miento com´n (implementaci´n de los m´todos en cada clase). En el caso de u o e la aplicaci´n para dibujar figuras geom´tricas, el comportamiento com´n es el o e u

3.4. INTERFACES.

65

hecho de que todas las figuras geom´tricas puede dibujarse. La implementaci´n e o concreta es el modo en que cada una de las clases hija se dibuja. El uso de esta buena pr´ctica en el Listado 3.5 es que las referencias deben a ser siempre del tipo m´s general posible (clase abstracta o interface como a veremos en la siguiente secci´n), y no de una clase concreta. Rescribamos el o c´digo del ultimo listado haciendo caso omiso de esta buena pr´ctica: o ´ a
1 2 3 4 5 6

C i r c u l o f i g u r a = new C i r c u l o ( ) ; f i g u r a . d i b u j a t e ( ) ; // D i b u j a r a un c´ r c u l o ´ ı f i g u r a = new T r i a n g u l o ( ) ; // E r r o r n u e s t r a f i g u r a e s un \ t e x t t t { C i r c u l o } no un \ t e x t t t { T r i a n g u l o } figura . dibujate () ; f i g u r a = new Cuadrado ( ) ; // E r r o r n u e s t r a f i g u r a e s un \ t e x t t t { C i r c u l o } no un \ t e x t t t { Cuadrado } figura . dibujate () ;

Como ves, no podemos aprovechar el comportamiento polim´rfico de nueso tras figuras ya que las referencias son de un tipo concreto y no de un tipo abstracto, la clase Figura. En una clase hija tambi´n podemos declarar como abstract alg´n m´todo e u e definido en la clase padre y que por lo tanto no es abstract. ¿Cuando nos puede interesar esta estrategia? Puede ser interesante para borrar el comportamiento por defecto que ofrece la clase padre, ya que si la clase hija a su vez es extendida por otra clases, estas deber´ definir el m´todo declarado abstract. Obviamente, ıa e si una clase hija declara como abstract un m´todo de la clase padre, aunque este e no fuese abstract en la clase padre, la tendremos que declarar como abstract.

3.4.

Interfaces.

Los interface son una nueva construcci´n del lenguaje Java que da un paso o m´s all´ en las clases abstract. Puedes pensar que un interface es como una a a clase abstract en la que todos sus m´todos son abstract. e Siguiendo con el ejemplo de las figuras geom´tricas de la Secci´n 3.3 podemos e o definir nuestro primer interface como:
1 2 3

public i n t e r f a c e D i b u j a b l e { public void d i b u j a ( ) ; }

Como ves, estamos usando la palabra reservada interface para indicar que estamos definiendo un interface. Las clases no extienden a los interfaces si no que los implementan y esto se indica con el uso de la palabra reservada implements de este modo:
1 2 3 4 5 6 7 8 9 10 11 12

public c l a s s T r i a n g u l o implements D i b u j a b l e { @Override public void d i b u j a ( ) { // C´ digo p a r a d i b u j a r un t r i ´ n g u l o o a } // S i g u e l a d e f i n i c i ´ n de l a c l a s e o } public c l a s s Cuadrado implements D i b u j a b l e { @Override public void d i b u j a ( ) { // C´ digo p a r a d i b u j a r un c u a d r a d o o

66
13 14 15 16 17 18 19 20 21 22 23

CAP´ ITULO 3. HERENCIA E INTERFACES

} // S i g u e l a }

d e f i n i c i ´ n de l a o

clase

public c l a s s C i r c u l o implements D i b u j a b l e { @Override public void d i b u j a ( ) { // C´ digo p a r a d i b u j a r un c´ r c u l o o ı } // S i g u e l a d e f i n i c i ´ n de l a c l a s e o }

F´ ıjate que para indicar que las clases est´n implementando un m´todo dea e clarado en un interface se anota el m´todo con @Override. e Y ahora, de nuevo, aparece la magia del polimorfismo y la vinculaci´n o din´mica: a una referencia de un tipo interface le podemos asignar cualquier a objeto de una clase que implemente ese interface, de modo que el c´digo del o siguiente listado es perfectamente v´lido: a
1 2 3 4 5 6

D i b u j a b l e f i g u r a = new C i r c u l o ( ) ; f i g u r a . d i b u j a ( ) ; // D i b u j a r ´ un c´ r c u l o a ı f i g u r a = new T r i a n g u l o ( ) ; f i g u r a . d i b u j a ( ) ; // D i b u j a r ´ un t r i a n g u l o a ´ f i g u r a = new Cuadrado ( ) ; f i g u r a . d i b u j a ( ) ; // D i b u j a r ´ un c u a d r a d o a

F´ ıjate que hemos utilizado una referencia de un tipo lo m´s amplio posible a Dibujable y el comportamiento se materializa en la creaci´n de las instancias o de clases concretas: Circulo, Triangulo o Cuadrado. En la definici´n de un interface podemos declarar cualquier n´mero de o u m´todos y tambi´n cualquier n´mero de constantes como en el siguiente ejemplo: e e u
1 2 3 4 5

public c l a s s i n t e r f a c e D i b u j a b l e { public s t a t i c f i n a l C o l o r BLANCO = new C o l o r ( 2 5 5 , 2 5 5 , 2 5 5 ) ; public s t a t i c f i n a l C o l o r NEGRO = new C o l o r ( 0 , 0 , 0 ) ; public void d i b u j a ( ) ; }

El anterior interface tiene contiene la declaraci´n de dos constantes, una o define el color BLANCO y la otra el color NEGRO. Una ventaja del uso de interfaces para modelar el comportamiento de las clases es que una clase puede implementar cualquier n´mero de interfaces. u Recuerda que en el caso de la extensi´n de una clase Java s´lo permite herencia o o simple. En el siguiente Listado se muestra un ejemplo de clase que implementa m´s de un inteface: a
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

// D e c l a r a c i ´ n de un nuevo \ t e x t t t { i n t e r f a c e } o public c l a s s i n t e r f a c e T r a n s f o r m a b l e { public void e s c a l a ( i n t sx , i n t s y ) ; public void d e s p l a z a ( i n t dx , i n t dy ) ; } // D e c l a r a c i ´ n de l a c l a s e o public c l a s s C i r c u l o implements D i b u j a b l e , T r a n s f o r m a b l e { @Override public void d i b u j a ( ) { // Aqu´ l a d e f i n i c i ´ n d e l m´ todo ı o e } @Override public void e s c a l a ( i n t sx , i n t s y ) {

3.4. INTERFACES.
16 17 18 19 20 21 22 23

67
d e l m´ todo e

// Aqu´ l a ı }

definici´n o

@Override public void d e s p l a z a ( i n t dx , i n t dy ) { // Aqu´ l a d e f i n i c i ´ n d e l m´ todo ı o e } }

Los interface al igual que las clases se pueden extender, y adem´s un a interface puede extender a m´s de un interface, la herencia simple es una a restricci´n en el ´mbito de las clases, los interface no poseen esta restricci´n. o a o En el siguiente listado tienes un ejemplo:
1 2 3

public i n t e r f a c e F i g u r a extends D i b u j a b l e , T r a n s f o r m a b l e { public void g i r a ( f l o a t a n g u l o ) ; }

Listado 3.6: Un interface que extiende a otros dos Con el uso de los interface la Buena pr´ctica de programar orientado al a interface toma a´n m´s fuerza. Por cierto no confundas la palabra reservada u a interface con el concepto de interface, este concepto se refiere a los m´todos e accesibles de una clase que son los que podemos utilizar para trabajar con la clase. Hasta aqu´ hemos visto el grueso del trabajo con herencia, hemos visto cual ı es su potencia y como trabajar con ella en Java. Y todo ello para llevarnos el siguiente jarro de agua fr´ ıa:

Buenas pr´cticas a En tus dise˜os software, favorece la composici´n frente a la herencia. n o ¿Qu´ significa esta buena pr´ctica? ¿No debemos utilizar nunca la herencia? e a No, todo lo contrario, la herencia es una t´cnica de POO a objetos muy potente e siempre que se la utilice bien. Un mal uso de la herencia es utilizarla para reaprovechar c´digo. La herencia significa que entre los conceptos que queremos o abstraer existe una clara relaci´n padre-hijo. No debemos utilizar la herencia o para reaprovechar c´digo entre clases que no est´n relacionadas l´gicamente a o a o traves de la herencia. Por ejemplo, tiene poco sentido que la clase Persona sea clase padre de la clase Ciudad simplemente porque una ciudad tenga un nombre. Este no es un buen uso de la herencia. La relaci´n entre esos entes en el mundo real no existe o y no debemos trasladarla de un modo artificial a nuestro c´digo. o La composici´n, significa que una clase contiene como atributos instancias o de otras clases. Este mecanismo de relaci´n entre clases es m´s flexible que la o a herencia y por lo tanto menos sensible a los cambios que tengamos que hacer en nuestro c´digo, m´s a´n si como referencias a las clases utilizamos interfaces o a u o clases abstractas. En definitiva, favorecer la composici´n frente a la herencia significa usar la o herencia s´lo cuando est´ justificado en nuestro dise˜o y no s´lo por comodidad. o e n o

68

CAP´ ITULO 3. HERENCIA E INTERFACES

3.5.

Enumeraciones.

Las enumeraciones son una construcci´n del lenguaje introducida en la vero si´n 5 de Java. Las enumeraciones nos sirven para definir listas enumeradas de o elementos y algo m´s, ya que en cierto modo son como clases, pueden tener a constructores, m´todos y atributos. El primer elemento de la enumeraci´n tiene e o la posici´n 0. o La unica restricci´n que tiene las enumeraciones sobre las clases es que las ´ o enumeraciones no se pueden extender ya que impl´ ıcitamente toda enumeraci´n o est´ extendiendo a la clase java.lang.Enum. Adem´s, el ´mbito de los consa a a tructores debe ser private o de paquete. La clase Enum nos proporciona algunos m´todos utiles que podemos utilie ´ zar en nuestra propias enumeraciones, como veremos a continuaci´n. Podemos o definir una enumeraci´n de una manera tan sencilla como la mostrada en el o siguiente Listado:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

public enum Semana { LUNES( " P r i m e r d ı a d e l a s e m a n a . " ) , ´ MARTES( " N i t e c a s e s n i t e e m b a r q u e s . " ) , MIERCOLES( " S i n c o m e n t a r i o s . " ) , JUEVES( " S i e m p r e e n m e d i o . " ) , VIERNES( " ´ l t i m o d ´ a d e t r a b a j o . " ) , U ı SABADO( " E m p i e z a e l f i n d e s e m a n a . " ) , DOMINGO( " M a ~ a n a d e n u e v o a t r a b a j a r . " ) ; n private S t r i n g c o m e n t a r i o ; // C o n s t r u c t o r a c c e s o de p a q u e t e o p r i v a t e . Semana ( S t r i n g c o m e n t a r i o ) { this . comentario = comentario ; } public S t r i n g g e t C o m e n t a r i o ( ) { return c o m e n t a r i o ; } }

Listado 3.7: Definici´n de una enumeraci´n para los d´ de la semana o o ıas La clase Enum nos proporciona el m´todo values() que devuelve un array e de String con todos los nombre de los elementos de la enumeraci´n. Cada o uno de los elementos de la enumeraci´n posee dos m´todos heredados de la o e clase Enum uno para conocer el nombre del elemento name(), y otro para conocer el ordinal del elemento dentro de la enumeraci´n ordinal(), adem´s, o a evidentemente, de los m´todos que nosotros mismo hayamos definido (el m´toe e do getComentario(), en el ejemplo del Listado 3.8. El siguiente Listado muestra un ejemplo de uso de la anterior enumeraci´n: o
1 2 3 4 5

f o r ( Semana d i a : Semana . v a l u e s ( ) ) { System . o u t . p r i n t l n ( d i a . name ( ) ) ; System . o u t . p r i n t l n ( d i a . o r d i n a l ( ) ) ; System . o u t . p r i n t l n ( d i a . g e t C o m e n t a r i o ( ) ) ; }

Listado 3.8: Uso de una enumeraci´n o

3.6. PAQUETES EN JAVA.

69

3.6.

Paquetes en Java.

Los paquetes son una construcci´n del lenguaje Java que nos permite agrupar o clases que est´n l´gicamente relacionadas en el mismo grupo o paquete. Para a o denotar que una clase pertenece a un determinado paquete, se indica en la definici´n de la clase con la palabra reservada package seguida del nombre del o paquete como en el siguiente ejemplo:
1 2 3 4 5

p a c k a g e agenda ; // E sta c l a s e

e s t a d e n t r o d e l p a q u e t e agenda ´

c l a s s P e r s o n a { // V i s i b i l i d a d d e n t r o d e l p a q u e t e // D e f i n i c i ´ n de l a c l a s e o }

Regla de convenci´n o Los nombres de paquetes se escriben en min´sculas. Si el nombre de un paquete u est´ compuesto por m´s de una palabra, se separan mediante puntos. a a Un nombre v´lido de paquete con m´s de una palabra es: agenda.datos o a a agenda.io.teclado. El ambito o visibilidad por defecto de una clase es el paquete, por ello, para ´ denotar que la visibilidad de una clase est´ restringida al paquete en la que a est´ definida no se utiliza ning´n modificador de acceso. a u Como ya sabemos, la visibilidad tambi´n se define sobre los miembros de e una clase de tal manera que un miembro puede se p´blico, privado, protegido u o de paquete. Veamos con mas detalle como se restringe la visibilidad con cada uno de estos modificadores de acceso. El modificador de acceso private es el m´s restrictivo de los cuatro, un a miembro privado no es accesible por ninguna otra clase. Podemos utilizar este modificador de acceso para ocultar completamente miembros de una clase. Una clase nunca se puede definir como private. El modificador de acceso por defecto, o de paquete, hace visibles los miembros de una clase al resto de clases dentro del mismo paquete. Una clase puede definirse como de paquete. El modificador de acceso protected, se comporta exactamente igual que el modificador por defecto pero adem´s permite que las clases hijas de la clase a protected puedan usar sus miembros a trav´s de la herencia aunque estas clases e hijas pertenezcan a paquetes distintos. El modificador de acceso public asigna la mayor visibilidad a los miembros de una clase. Un miembro p´blico es accesible desde cualquier otra clase sin u importar el paquete en el que est´ definido, o si existe una relaci´n padre-hija e o entre ellas. La Tabla 3.1 muestra todas las posibilidades de acceso entre miembros de clases. En la Figura 3.1 su muestra gr´ficamente las posibilidades seg´n el modifia u cador de acceso empleado. A partir de la versi´n 5 de Java se introdujo el concepto de import static o con la intenci´n de facilitar la escritura de c´digo. La idea de los import static o o

70

CAP´ ITULO 3. HERENCIA E INTERFACES

¿Es accesible? Misma clase Clase/subclase del paquete Subclase otro paquete Clase otro paquete

private SI NO NO NO

paquete SI SI NO NO

protected SI SI SI 3 NO

public SI SI SI SI

Tabla 3.1: Modificadores de acceso y su visibilidad

Figura 3.1: Visibilidad de los miembros seg´n el modificador de acceso utilizado. u

visibilidad por defecto). No obstante. Aunque lo aconsejable es que. a 3.java. public c l a s s ClaseQueUsaImports { public void otroMetodo ( ) { metodo ( ) . De igual modo interface o LeerDatos es un interface como otro cualquiera. private S t r i n g a p e l l i d o s . private S t r i n g p u e r t a .3. en un mismo fichero podemos o definir m´s de una clase siempre que s´lo una de ellas sea public y su nombre a o coincida con el del fichero. s u b p a q u e t e . Un caso de o uso comunmente extendido es en las pruebas unitarias. con independencia del ´mbito. para incluir los miembros est´ticos de los frameworks como JUnit . private D i r e c c i o n d i r e c c i o n . tal y como se muestra en el siguiente Listado: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // D e f i n i c i ´ n de una c l a s e o package p a q u e t e . pero por otro se pierde la perspectiva de la pertenencia de los miembros o static a sus clases concretas. a efectos de ı programaci´n es una nueva clase como cualquier otra. public c l a s s C l a s e { public s t a t i c void metodo ( ) { // D e f i n i c i ´ n d e l m´ todo o e } } // D e f i n i c i ´ n de o t r a c l a s e o import s t a t i c p a q u e t e . s u b p a q u e t e . Clases e interface anidados Hasta este momento hemos definido cada una de nuestras clases en un fichero independiente con extensi´n . private S t r i n g p o b l a c i o n . CLASES E INTERFACE ANIDADOS 71 es incluir una clase o un paquete de clases y poder llamar a los miembros est´tia cos de las clases importadas sin necesidad de escribir el nombre de la clase. Hay que utilizarlos con precauci´n. o Si embargo. C l a s e .9: Uso de una enumeraci´n o A la clase Direccion as´ definida se le llama clase interna y. por un lado facilitan la codificaci´n. cada clase est´ definida en un fichero distinto. } Listado 3.7.7. dentro de la definici´n de una clase podemos definir nuevas o clases e interface como se muestra en el siguiente Listado: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public c l a s s P e r s o n a { private S t r i n g nombre . } public i n t e r f a c e L e e r D a t o s { public S t r i n g getNombre ( ) . El ´mbito o visibilidad del resto de clases debe ser el a paquete (recuerda. private S t r i n g p r o v i n c i a . Los import static son un arma de doble filo. private i n t numero . ya que a e esto favorece el mantenimiento del c´digo. . private c l a s s D i r e c c i o n { private S t r i n g c a l l e .

Modifica tu agenda para que sea capaz de trabajar con los nuevos tipos de datos definidos. Ejercicios. HERENCIA E INTERFACES Hay un caso particular de creaci´n de clases internas en el que la nueva clase o no recibe ning´n nombre como se muestra en el siguiente Listado. cosa que como sabes no est´ permitida. @Override public S t r i n g getNombre ( ) { return nombre .10: Uso de una enumeraci´n o F´ ıjate que en la l´ ınea 17 parece que se est´ intentando instanciar un a interface. 3. Lo que est´ ocurriendo a a es que se est´ creando e instanciando una nueva clase sin nombre. Amplia la clase Empresa para que contenga informaci´n sobre la direcci´n o o de la sede de la empresa. ya que por ser o an´nima no tienen nombre y por lo tanto no podemos definir sus constructores. continuaci´n u o del anterior: 17 18 19 20 21 22 23 public L e e r D a t o s l e c t o r = new L e e r D a t o s ( ) { private P e r s o n a p e r s o n a .72 CAP´ ITULO 3. y en el Cap´ a ıtulo 14 dedicado a la programaci´n concurrente o con hilos. que est´ implementando el interface LeerDatos. para que pueda trabajar. 4. Se est´ creando o a a e instanciando la clase interna an´nima al mismo tiempo. y por lo tanto a an´nima. Cuestiones. 1. o Las clases internas an´nimas son una construcci´n muy potente del lenguaje. Amplia la clase Persona para que contenga informaci´n sobre la direcci´n o o de residencia de la persona. } Listado 3. de modo transparente. o o Veremos toda su potencia en el Cap´ ıtulo 11 dedicado a la creaci´n de interfaces o gr´ficos de usuario. . Modifica tu implementaci´n de la clase Agenda que escribiste en el ejercicio o 3 del Cap´ ıtulo 2. 2. ¿Tiene sentido declarar los constructores de una clase como private? ¿Se podr´n crear instancias de una clase en la que todos sus constructores son a private? ¿Se podr´ extender una clase en la que todos sus constructores a son private?. tanto con instancias de tipo Persona como con instancias de tipo Empresa. este es el unico moo ´ mento en el que se puede instanciar una clase interna an´nima. 1.

e .7.3. El cap´ ıtulo 7 del libro de Sierra y Bates [3] expone gr´ficamente todos los a conceptos relacionados con la herencia en Java. Para una exposici´n m´s detallada sobre clases e interface anidados una o a excelente referecia es el cap´ ıtulo 5 del libro de James Gosling [2]. Para un fundamentado razonamiento de porqu´ favorecer la composici´n e o sobre la herencia v´ase el item 14 de la referencia [4]. CLASES E INTERFACE ANIDADOS 73 Lecturas recomendadas.

74 CAP´ ITULO 3. HERENCIA E INTERFACES .

Obteniendo informaci´n del repositorio . . . . .1. . 75 . . . . . si no que o o conozca las herramientas de desarrollo de software m´s utilizadas y que. . o Trabajo con repositorios .5. . . . Integraci´n con Eclipse . . desde un a principio. 76 .1. . . . . o . .4. ¿Qu´ es un sistema de control de versiones? e Principales caracter´ ısticas de Subversion . . . Creaci´n de un repositorio . . . el objetivo de este libro es mostrar o o c´mo desarrollar proyectos inform´ticos con tecnolog´ Java en un contexto o a ıa de desarrollo lo m´s cercano posible al que el programador va a encontrar en a cualquier organizaci´n de desarrollo de software.3. . que. . . . . 77 . . 4. 78 . . 76 . . . 4. . incluso trabajando individualmente. . a o Como ya se coment´ en la introducci´n. . . . 4. En este cap´ ıtulo se presenta la herramienta de control de versiones Subversi´n. 4. . . . . . se integre suavemente en un equipo de desarrollo. . . .2. Lo que hace realmente valioso o a un programador no es s´lo que conozca lenguajes de programaci´n. 82 . Y esta integraci´n o tiene mucho que ver con toda la experiencia que posea con el trabajo en grupo y las herramientas que lo favorecen. se hace imprescindible en todo o proyecto para la gesti´n de las diferentes versiones del proyecto a medida que o este evoluciona.4. . . o 4. .Cap´ ıtulo 4 Control de versiones con Subversion Contenidos 4. . 84 Introducci´n o Este es el primer cap´ ıtulo dedicado a una herramienta utilizada en el desarrollo de proyectos inform´ticos y no directamente al lenguaje de programaci´n Java.

las opciones son las que aparecen en la Tabla 4. SUBVERSION 4. Y en este ultimo caso. 4. cuando empieza a trabajar en el proyecto. En la tercera opci´n se utiliza Subversion a trav´s de un t´nel ssh. Principales caracter´ ısticas de Subversion Subversion es una herramienta centralizada de ayuda al control de versiones. Su uso no es exclusivo en el desarrollo de proyectos inform´ticos.1. ´ Por otro lado. o sobre un servidor en red. El concepto central en Subversion es el Repsositorio . probablemente coordinado por un jefe de proyecto. hace una copia local del contenido del repositorio. En la segunda de las opciones se accede utilizando el servidor ad-hoc que viene incluido en la propia distribuci´n de o Subversion. resolviendo los posibles conflicto o que hayan aparecido. o e u La cuarta opci´n permite el acceso a un repositorio a trav´s de Apache y el o e . o Una de las caracter´ ıstica principales de Subversion es que las actualizaciones en el repositorio son incrementales. se puede trabajar con Subversion de manera local sobre el propio sistema de ficheros donde se realiza el desarrollo. En este escenario. En la primera de las opciones de la Tabla 4. el c´digo va ıa o a estar sujeto a continuas modificaciones por parte de todos los programadores del equipo.2.76 CAP´ ITULO 4. si no que a puede utilizarse en cualquier proyecto que requiera de un sistema autom´tico a de control de versiones. se dice que se ha creado una nueva versi´n del proyecto en el repositorio. Otra necesidad del equipo es o garantizar que todos los programadores pueden disponer de la ultima versi´n ´ o del c´digo del proyecto. La elecci´n del modo de trabajo con Subversion se ver´ reo o a flejada en la URL que utilizaremos para acceder al repositorio. o como un o m´dulo de Apache. Sea cual sea la metodolog´ que se utilice en el desarrollo del proyecto. se actualiza la versi´n de todos los ficheros existentes en el o repositorio y no unicamente de los ficheros que se han modificado. Al finalizar esta fase.1. cada vez que se realiza una modificaci´n o o o en el repositorio. Por repositorio se entiende la ultima versi´n del proyecto que existe en el sistema de control de ´ o versiones. el servidor utilizado puede ser el propio servidor ad´ hoc que viene incluido con la distribuci´n de Subversion (svnserve). s´lo se actualizan los ficheros que se han o modificado con respecto a la versi´n anterior. El paradigma que Suversion utiliza es Copia-Modificaci´n-Fusi´n (Copyo o Modify-Merge en ingl´s).1 se accede directamente al repositorio en el sistema de ficheros. Otra caracter´ o ıstica es relativa a la numeraci´n de la versi´n del repositorio. de manera autom´tica. Dependiendo del protocolo utilizado. no es raro encontrar que dos programadores han modificado el mismo fragmento de c´digo de modo que se llegue a conflictos o cuando se quiere unificar el c´digo del proyecto. o Un Sistema de Control de versiones es una herramienta software que. En este paradigma. modifica su copia local y finalmente fusiona sus modificaciones locales con el c´digo del repositorio. se encarga de facilitar la gesti´n de las versiones del c´digo a o o de un proyecto de manera centralizada. cada uno de los miembros del e equipo. ¿Qu´ es un sistema de control de versiones? e El escenario m´s usual en el desarrollo de software es un equipo formado por a varios programadores.

El o e directorio hooks contiene scripts b´sicos para el trabajo con Subversion. CREACION DE UN REPOSITORIO file:/// svn:// svn+ssh:// http:// https:// El repositorio se encuentra en el disco local.. o El acceso al repositorio ser realiza con encriptaci´n SSL a o trav´s de Apache con el m´dulo WebDAV. El acceso al repositorio se realiza a trav´s del servidor e svnserve. en la ultima opci´n se accede al respositorio a trav´s de un servidor ´ o e Apache con encriptaci´n ssl (del ingl´s Secure Socket Layer ). en una consola escribir´ ıamos: ~$ svnadmin create ~. En las pr´ximas o secciones utilizaremos el protocolo svn:// para acceder a un repositorio a trav´s e del servidor svnserve. Creaci´n de un repositorio o La creaci´n de un nuevo repositorio se hace utilizando la herramienta svnadmin o incluida en la distribuci´n de Subversion. es el coraz´n del repositorio. El acceso al repositorio se realiza a trav´s del servidor e svnserve utilizando un t´nel SSH u El acceso al repositorio se realiza a trav´s de Apache con el e m´dulo WebDAV.1: Tipos de acceso a los repositorios Subversion. README. .3. en nuestro disco duro local. m´dulo WebDAV (del ingl´s Web-based Distributed Authoring and Versioning). ./Repositorio Si examinamos el contenido del directorio veremos que se han creado los siguiente subdirectorios y ficheros dentro del directorio . El directorio db es el que emplea Subversion para registrar todos los cambios realizados en el contenido del repositorio. Para crear un repositorio Subversion en este directorio.txt conf db format hooks locks El fichero README. o el directorio conf es donde se encuentran los ficheros de configuraci´n para el o acceso al servidor de Subversion. s´lo a trav´s de las herramientas que proporciona Subversion. o e Finalmente. e o 77 Tabla 4./Repositorio: drwxr-xr-x drwxr-xr-x -rw-r--r-drwxr-xr-x drwxr-sr-x -r--r--r-drwxr-xr-x drwxr-xr-x 8 32 1 5 16 1 11 4 oscar oscar oscar oscar oscar oscar oscar oscar staff staff staff staff staff staff staff staff 272 1088 229 170 544 2 374 136 23 23 23 23 23 23 23 23 may may may may may may may may 18:48 18:48 18:48 18:48 18:48 18:48 18:48 18:48 .txt contiene un aviso sobre c´mo debe ser usado este o directorio. o e Cada una de estas opciones tiene sus ventajas y desventajas. 4./Repositorio (directorio Repositorio en la ra´ de nuestro directoız rio de usuario).3.´ 4. El dia rectorio locks es utilizado por Subversion para los bloqueos del repositorio. Finalmente. El trabajo con Subversion es independiente del protocolo utilizado. Supongamos que hemos creado el dio rectorio .

de este modo: . authz passwd svnserve. en particular podemos restringir los permisos de lectura y escritura para cada uno de los usuarios a cada uno de los directorios que contiene nuestro repositorio a trav´s de lo especificado en el fichero authz. . por claridad.78 CAP´ ITULO 4. Despu´s de descomentar esta l´ e ınea debemos editar el fichero passwd y a˜adir los usuario y sus claves siguiendo el ejemplo que encontraremos en ´l: n e # harry = harryssecret # sally = sallyssecret oscar = clave_secreta Con esto ya tenemos activa la configuraci´n m´s b´sica para nuestro repoo a a sitorio. suponiendo que nos encontramos en el directorio CopiaTrabajo. al que s´lo puede acceder el usuario oscar con permisos de lectura y o escritura para todos los directorios y ficheros del repositorio. A partir de ahora ya podemos empezar a trabajar con nuestro repositorio. Para activar la opci´n de acceso a trav´s de usuario autorizado hay que o e descomentar la l´ ınea: password-db = passwd esta l´ ınea indica el nombre del fichero de pares usuario/clave para nuestro repositorio. SUBVERSION A efectos pr´cticos. /workspace/NombreProyecto. lo que implica que todos los usuarios dados de alta en el fichero passwd tendr´n acceso total a todos los a directorios y ficheros del repositorio. Trabajo con repositorios Supongamos que..conf indicamos las opciones de acceso al repositorio. El primer paso que debemos dar es importar el contenido del directorio CopiaTrabajo al repositorio Subversion. Su contenido es el siguiente: o drwxr-xr-x drwxr-xr-x -rw-r--r--rw-r--r--rw-r--r-5 8 1 1 1 oscar oscar oscar oscar oscar staff staff staff staff staff 170 272 1080 309 2279 23 23 23 23 23 may may may may may 18:48 18:48 18:48 18:48 18:48 . /CopiaTrabajo (en Eclipse nuestra copia de trabajo ser´ algo como . El siguiente paso antes de empezar a trabajar con nuestro repositorio es iniciar el servidor de Subversion del siguiente modo: ~$ sudo svnserve --daemon Es necesario tener permisos de administrador para iniciar el servidor de Subversion como un proceso daemon.conf En el fichero svnserve. el directorio donde vamos a realizar tareas de configua raci´n es conf.4. 4. Como ejemplo unicamente vamos a especificar los usuarios y sus claves en ´ el fichero passwd sin modificar el fichero authz. elegimos nombrar al directorio que va a mantener nuestra copia de trabajo como . no es necesario que a los nombre del proyecto y del repositorio coincidan). y los usuarios y claves de acceso e al repositorio en el fichero passwd.

svn://localhost/home/oscar/Repositorio/ trunk -m "Import inicial del proyecto" El . dentro del directorio creado en el paso anterior creamos un fichero de definici´n de clase llamado Saludo. Para seguir la estructura t´ ıpica de un proyecto Eclipse creemos el directorio src para contener los fuentes del proyecto. En o o este momento se solicitar´ la clave del usuario que hemos activado en el fichero a de configuraci´n passwd.java ~/CopiaTrabajo$ svn add Saludo. Ahora. o Te habr´s dado cuenta de que estamos a˜adiendo el subdirectorio trunk al a n repositorio.java. a posteriori. corresponde al directorio actual. Finalmente -m ¨mport inicial del o I proyecto" es un mensaje descriptivo de lo que estamos haciendo para que. Cualquier modificaci´n o en el directorio de trabajo la tenemos que hacer utilizando Subversion.4.java .java A src/Saludo. resulte c´modo encontrar una determinada versi´n del proyecto. a Buenas pr´cticas a En nuestro directorios Subversion es recomendable crear los siguiente subdirectorios: trunk: Directorio donde se encuentra la versi´n en desarrollo del proyecto. o branches: Directorio donde se encuentran las posibles ramificaciones del proyecto. En este momento tenemos sincronizada la copia en el repositorio con nuestra copia de trabajo. necesitamos hacer el checkout del repositorio hacia nuestra copia de trabajo de este modo (f´ ıjate en el punto final ((. Para que los ficheros y directorios en CopiaTrabajo se conviertan en una copia de trabajo real. luego. tags: Directorio donde se encuentran las versiones finales (releases). y la direcci´n que aparece a continuao ci´n svn://localhost/home/oscar/Repositorio/trunk corresponde a la dio recci´n donde se encuentra el repositorio.)) para indicar que el checkout lo queremos hacer sobre el directorio actual): ~/CopiaTrabajo$ svn checkout svn://localhost/home/oscar/Repositorio/ trunk . y le indicamos a Subverion que lo o a˜adimos a nuestra copia local: n ~/CopiaTrabajo$ touch src/Saludo. esto forma parte de las buenas pr´cticas de trabajo con Subversion. TRABAJO CON REPOSITORIOS 79 ~/CopiaTrabajo$ svn import . en la consola debemos escribir lo siguiente para crear un directorio que Subversion pueda sincronizar con el repositorio: ~/CopiaTrabajo$ svn mkdir src A src Subversion nos indicar´ que se ha a˜adido (A) el directorio src a la copia a n local.4.

la o a o opci´n -v significa verbose. ´ o A la ultima versi´n se le llama HEAD. Ahora realiza alg´n peque˜o cambio en el ´ o u n fichero Saludo. En un equipo de desarrollo cualquier otro programador puede realizar cambios sobre alg´n fichero en el Repositorio.80 CAP´ ITULO 4. para conocer en todo momento cual es el estado de nuestra copia local con respecto a la ultima versi´n existente en el Repositorio ´ o podemos escribir: ~/CopiaTrabajo$ svn status -u * 3 src/Saludo. Commit de la revisi´n 3. src src/Saludo. Subversion te lo o pedir´. Para n conocer el estado de tu copia local con respecto a la ultima versi´n existente en ´ o el Repositorio puedes utilizar la instrucci´n status con la opci´n -v tecleando o o en consola: ~/CopiaTrabajo$ svn status -v 1 1 oscar 2 2 oscar M 2 2 oscar . o Donde se nos informa que la ultima versi´n disponible en el repositorio es la 2. Veamos el resultado de un commit escribiendo: ~/CopiaTrabajo$ svn commit -m "Una modificaci´n en el fichero o Saludo.java Estado respecto a la revisi´n: 5 o . y en el pr´ximo commit se subir´ la versi´n local al repositorio. o puede a˜adir nuevos ficheros y u n directorios al repositorio.java. Commit de la revisi´n 2.java no se ha enviado al repositorio.java se ha modificado (letra inicial M). s´lo se ha marcado para que la pr´xima vez que se haga un commit este fichero o o se a˜ada efectivamente al Repositorio. SUBVERSION En este momento el fichero Saludo. si lo olvidas.java Transmitiendo contenido de archivos .java" Enviando src/Saludo. n Lo siguiente que debemos hacer es subir al repositorio todos los cambios que hemos hecho en nuestra copia local.java Transmitiendo contenido de archivos . que no ha habido ning´n problema al subir u la nueva copia local al Repsositorio. de nuevo.java Este texto nos informa que el fichero Saludo. o Este texto nos informa. La respuesta que ver´s en consola por parte de Subversion ser´ parecida a a a a esta: A~adiendo n src A~adiendo n src/Saludo. de este modo: ~/CopiaTrabajo$ svn commit -m "A~adiendo la clase Saludo al n repositorio" Observa que es necesario a˜adir un mensaje descriptivo de lo que estamos n haciendo con la opci´n -m ”Texto del mensaje”. como a˜adir un simple comentario y graba tu fichero. es decir queremos una descripci´n detallada del o o estado de la copia local.

java Transmitiendo contenido de archivos .java Actualizado a la revisi´n 5. luego es necesario que primero actua´ o licemos nuestra copia local a la ultima versi´n en el repositorio. si no la incluimos la comparaci´n se rea´ o o lizar´ entre la copia local y la ultima versi´n que nos descargamos desde el a ´ o Repositorio que puede no ser la versi´n HEAD del Repositorio. en nuestra copia local.java’ est´ desactualizado a Este error se debe a que nuestra copia local se encuentra en la versi´n 3 y o la ultima versi´n en el repositorio es la 5.java (revisi´n: 3) o +++ src/Saludo.3 @@ public class Saludo { + // Un comentario } \ No newline at end of file Si vemos un signo ((+)) al inicio de la l´ ınea significa que esa l´ ınea se ha a˜adido n con respecto de la ultima actualizaci´n que hicimos (que no tiene porqu´ coin´ o e cidir con la ultima versi´n que existe en el repositorio).4.src/Saludo.svn: Fall´ el commit o (detalles a continuaci´n): o svn: El archivo ’/trunk/src/Saludo. Si dos programadores no modifican las mismas l´ ıneas de c´digo. la ultima versi´n en ´ o el Repositorio m´s nuestros cambios que se han a˜adido sin conflicto.java (copia de trabajo) @@ -1.4. En este caso tenemos. Si queremos conocer cual es el estado ´ o local de nuestros fichero con respecto de la ultima actualizaci´n escribimos: ´ o ~/CopiaTrabajo$ svn diff Index: src/Saludo. El * indica que el o fichero Saludo. Si ahora intentamos hacer un commit obtendremos el siguiente error: ~/CopiaTrabajo$ svn commit -m "Intentando un commit que fallar´" a Enviando src/Saludo. la letra G al inicio de la l´ ınea indica que Subversion ha sido capaz de mezclar (merge en ingles) la ultima revisi´n existente en el Repositorio con ´ o los cambios locales en nuestro fichero y no ha encontrado conflictos.java en mi copia de trabajo est´ en la versi´n 3 mientras que a o en el repositorio la ultima versi´n es la 5.java ============================================== --. ahora ya a n podemos hacer de nuevo un commit: . y en segundo ´ o lugar que enviemos los cambios.2 +1. TRABAJO CON REPOSITORIOS 81 La opci´n -u indica que se compare nuestra versi´n local con respecto a o o la ultima versi´n en el Repositorio. Para actualizar nuestra copia local a la ultima ´ versi´n del Repositorio (HEAD) escribimos: o ~/CopiaTrabajo$ svn update G svn/Saludo. Si la l´ ´ o ınea empieza con un signo ((-)) indica que esa l´ ınea sea ha eliminado. no aparecer´ ning´n conflicto cuando Subo a u version intente mezclar el c´digo de nuestra copia local con el de la copia en el o Repositorio. si no que las discrepancias o aparecen el l´ ıneas de c´digo distintas. o Esta vez.

cuando una l´ ınea ha sido modificada por dos o m´s a programadores.7 @@ @author Oscar public class Saludo { +<<<<<<< .java. SUBVERSION ~/CopiaTrabajo$ svn commit -m "Ya actualizado subo mis cambios" Enviando src/Saludo. En este caso debemos resolver el conflicto a mano. Subversion nos proporciona instrucciones para conocer en cualquier momento informaci´n sobre o el repositorio.java Se resolvi´ el conflicto de ’src/Saludo. tal y como se muestra a continuaci´n: o .82 CAP´ ITULO 4. podemos seguir trabajando con nuestro repositorio como hasta el momento o hasta que aparezca un nuevo conflicto.4.java (copia de trabajo) @@ -1.src/Saludo. y en a o ı el momento de intentar hacer un update seremos informados de que existe un conflicto. o Ahora s´ que ha tenido ´xito el commit puesto que la versi´n de nuestra copia ı e o local coincide con la ultima versi´n en el repositorio. aqu´ mostramos algunas de las opciones o o ı para conocer el estado del repositorio y de nuestra copia local. Subversion no sabr´ c´mo resolver el conflicto por s´ solo. eliminando todas las l´ ıneas insertadas y manteniendo el comentario) se lo indicamos a Subversion del siguiente modo: ~/CopiaTrabajo$ svn resolved Saludo.mine +======= // Un comentario.1. de hecho. ´ o En otras ocasiones. y una vez resuelto (por ejemplo. las l´ ıneas extra que aparecen en el c´digo se han a˜adido realmente al o n fichero Saludo.java’ o De nuevo.java (revisi´n: 7) o +++ src/Saludo. 4. un poco largo +>>>>>>> .java ================================================ --.java Transmitiendo contenido de archivos . Commit de la revisi´n 6. Obteniendo informaci´n del repositorio o Sin ´nimo de ser exhaustivos con respecto a las posibilidad para obtener infora maci´n sobre un repositorio Subversi´n. Con svn log obtenemos informaci´n sobre los mensajes que fueron adjuno tados con cada nuevo commit.r7 } \ No newline at end of file En este mensaje se nos informa que hay un conflicto ya que nuestra copia local contiene la l´ ınea del comentario que ha sido eliminada en el repositorio. como en el caso siguiente: ~/CopiaTrabajo$ svn diff Index: src/Saludo.4 +1.

el ultimo c´digo indica que el fichero ha quedado bloqueado. Si por alguna raz´n alguna de las tareas pendientes no se puede llevar a cabo.4. con lo que obtendremos informaci´n del modo siguiente: o ? ! A C D M L Punto. antes del nombre de cada fichero.4. realizar cambios en la copia local. podemos indicarlo o con la opci´n -r como en el siguiente ejemplo: o caterva:LibroJava oscar$ svn log -r 10 -------------------------------------------------------------r10 | oscar | 2010-06-25 10:31:51 +0200 (vie.java Principal. si estamos interesados en el estado del repositorio para una determinada revisi´n o podemos utilizar la opci´n -r tal y como se muestra en el siguiente ejemplo: o caterva:LibroJava oscar$ svn list -r 3 clases/ herencia/ Si lo que nos interesa es conocer el estado de las ultimas modificaciones de ´ nuestra copia local con respecto al repositorio.java Nuevo.java La letra may´scula de la primera columna. En el momento en que se desea sincronizar la copia local con la remota.java Ejemplo. 25 jun 2010) | 1 line Para el Cap´tulo de Entrada/Salida. a u .java Punto3D. ´ o Esta situaci´n puede ocurrir cuando. TRABAJO CON REPOSITORIOS 83 -------------------------------------------------------------r2 | oscar | 2010-05-17 09:44:03 +0200 (lun. podemos utilizar la instrucci´n o svn status. por ejemplo. se bloquean los ficheros que se van a sincronizar. o ı -------------------------------------------------------------r1 | oscar | 2010-05-17 09:43:33 +0200 (lun. el resultado o ser´ que alg´n fichero puede quedar bloqueado. al intentar hacer un commit o la conexi´n con el repositorio remoto se pierde y no se puede acabar el env´ Al o ıo. -------------------------------------------------------------Si estamos interesados en alguna revisi´n en particular.java Hola. 17 may 2010) | 1 line Initial import.2. De nuevo.java PruebaPunto. u es un c´digo que nos indica el estado del fichero o directorio con el siguiente o significado: En la tabla 4. ı -------------------------------------------------------------Para conocer el estado del repositorio podemos usar svn list. 17 may 2010) | 1 line C´digo del cap´tulo Clases. Subversion va acumulando en una lista todas las tareas pendientes.

ver´s como todos los paquetes o a de clases necesarios para el nuevo plug-in se descargan hacia tu m´quina.2: C´digos con informaci´n sobre el estado de la copia local del fichero o o sobre la copia remota. En la siguienı o te ventana se te mostrar´n a modo de informaci´n todos los paquetes que se a o instalar´n.tigris. aunque algunos de ellos son opcionales.6 y su URL ´ o es http://subclipse. se eliminar´ el bloqueo sobre a los ficheros. Al pulsar Enter te aparecer´n todos los plug-ins a disponibles en esa direcci´n. En la siguiente ventana se te pide que aceptes a los t´rminos de la licencia.84 ? ! A C D M L CAP´ ITULO 4. Finalmente. Integraci´n con Eclipse o Aunque el trabajo con Subversion desde l´ ınea de instrucciones es bastante sencillo. si lo que nos interesas conocer con detalle son los cambios producidos en los ficheros entre la copia local y la existente en el repositorio podemos utilizar svn diff. Pulsa de nuevo Next.org/subversive/). SUBVERSION El fichero no se est´ a˜adido al repositorio a n No existe una copia local de este fichero El fichero se ha marcado para a˜adir al repositorio n Existen conflictos entre la copia local y el repositorio El fichero se ha marcado para ser borrado del repositorio Hay modificaciones en la copia local del fichero El fichero est´ bloqueado a Tabla 4.6.x 2 En 1 Estas . as´ que marca todos ellos y pulsa el bot´n Next.5. (http://subclipse. para ello selecciona la opci´n I accept the terms and e o of the license agreements y pulsa el bot´n Finish. la mejor idea es probar algunos de ellos y quedarnos con el que m´s a se adapte a nuestra forma de trabajo. La ultima versi´n del plug-in Subclipse puedes encontrarla en la direcci´n ´ o o http://subclipse.tigris.tigris. y si queda alguna o pendiente. Para eliminar los bloqueos podemos utilizar la instrucci´n svn cleanup.4. En la secci´n Dowload and Install encontrar´s o a la ultima release y la URL desde donde instalar el plug-in. Hacia a el final de la instalaci´n se abrir´ una ventana de advertencia indic´ndote que o a a instrucciones son v´lidas para la versi´n 3. y precisamente n existen excelentes plug-ins para trabajar con Subversion desde Eclipse.6 (Helios) de Eclipse a o el momento de escribir este libro la ultima versi´n de este plug-in es la 1. Elegir entre uno u otro acaba siendo cuesti´n de gustos ya que todos ellos son o excelentes.org. intenta realizarla.eclipse. Como se coment´ en la Secci´n 1. ´ Para instalar un plug-in 1 selecciona la opci´n Help → Install new Software o se abrir´ una ventana con una secci´n Work with donde debes introducir la a o URL del plug-in Subclipse 2 .1. 4. o esta instrucci´n comprueba el listado de tareas a realizar.5 (Galileo) y la 3.org/). aunque existe otros excelentes plug-ins como Subversive (http://www. resulta interesante no tener que abandonar Eclipse para trabajar con el Repositorio de nuestro proyecto. conviene o instalarlos todos. se puede o o a˜adir nueva funcionalidad a Eclipse instalando nuevos plug-ins. al final de lo cual.org/update_1. Uno de ellos es Subclipse.

. En esta nueva vista es donde puedes a˜adir conexiones a los repositorios n Subversion que quieras.´ 4. Al hacerlo se u abrir´ una ventana. en ellaselecciona SVN Repository Exploring. f´ ıjate que no hemos introducido trunk al final de la URL. pulsa Finish. a solo nos restar´ hacer bot´n derecho sobre el nombre del fichero y seleccionar a o Commit. pasaremos u a la perspectiva Team Synchronization donde nos aparecer´ toda la informaci´n a o de sincronizaci´n con el repositorio. de manera gr´fica. Para abrir esta nueva Perspectiva.. INTEGRACION CON ECLIPSE 85 parte del software que est´s instalando no est´ firmado..3. Si existe conflicto en alguno de nuestros ficheros de c´digo podemos abrir una o Vista donde se nos muestra.. Finalmente. y en la nueva ventana despliega la opci´n Java y seleco ciona la opci´n Java Project. a partir de aqu´ el Wizard es el que ya conoces o ı.. se u a abrir´ una ventana solicit´ndote la URL del repositorio al que te quieres coa a nectar. se abrir´ una nueva ventana con la opci´n a a o seleccionada por defecto Check out as a project configured using New Project Wizard. vamos a crear una conexi´n al repositoo rio local que tenemos en svn://localhost/home/oscar/Repositorio/trunk (esta direcci´n no tiene por qu´ coincidir con la que hayas elegido t´). pulsa el bot´n Yes y o a o Eclipse se reiniciar´ y ya podr´s usar el plug-in reci´n instalado. selecciona la opci´n o de men´ de Eclipse Window → Show perspective → Other. por esta vez pulsa la a a tecla OK para seguir con la instalaci´n. el estado de nuestra copia local y el estado del fichero en el repositorio. es decir la informaci´n o que en consola obten´ ıamos con svn diff. introduce svn://localhost/home/oscar/Repositorio. y utilizas cada vez que quieres crear un nuevo proyecto. as´ que simplemente ı introduce un nombre para el nuevo proyecto y pulsa Finish.java. despliega la URL y ver´s bajo ella a el directorio trunk y bajo ´l. se abrir´ una Vista con el a t´ ıtulo SVN Repositories que inicialmente estar´ vac´ a ıa. Una vez resueltos los conflictos pulsamos el bot´n derecho del o o rat´n y elegimos Mark as Merged para indicar que hemos resuelto los conflictos o y que nuestra copia local est´ lista para ser subida al repositorio (commit). Finalmente se te pedir´ que para acao a bar con la instalaci´n est´ recomendado reiniciar Eclipse. Como ejemplo. pulsado el bot´n derecho del rat´n sobre el proyecto en Eclipse y a o o eligiendo del men´ contextual Team → Synchronize with repository.. para o e u ello. a a e Ahora. Dentro de esa a nueva Perspectiva puedes abrir una nueva vista con la opci´n de men´ Window o u → Show View → SVN Repositories. sobre la vista SVN Repositories pulsa el bot´n derecho de tu rat´n y en o o el men´ emergente que aparecer´ selecciona New → Repository Location. La interpretaci´n de los iconos es la que se o o muestra en la Tabla 4. ahora la podemos obtener. al mismo tiempo. con la enorme ventaja de que todo el trabajo con el repositorio puedes hacerlo desde el propio Eclipse.. . Para hacer el chekout del e repositorio selecciona trunk con el bot´n derecho y en el men´ contextual que o u te aparecer´ selecciona Checkout. ver´s que la nueva a URL te aparece en la vista SVN Repositories. pulsa Finish.5.. Cada vez que queramos ver las discrepancias entre nuestra copia local y la existente en el repositorio. para que podamos resolver los conflictos c´modamente. el fichero Saludo. se abrir´ una ventana para introducir un comentario para el commit a y pulsamos OK. Al final de este proceso tendr´s una copia local del proyecto en Eclipse soa bre la que puedes trabajar tal y como trabajas sobre cualquier otro proyecto Eclipse. dispondr´s de una nueva Perspectiva que te permitir´ visualizar tus a a repositorios Subversion.

86 Flecha azul hacia la izquierda Flecha gris hacia la derecha Doble flecha roja CAP´ ITULO 4. Otra referencia m´s compacta es el cap´ a ıtulo 4 del la referencia [13].org/.3: Significado de los iconos en la perspectiva Team Synchronization Lecturas recomendadas. SUBVERSION La versi´n del repositorio es m´s actual o a que la copia local. La referencia obligada para conocer cualquier aspecto de Subversion es [7]. donde se detallan los puntos principales para empezar a trabajar con Subversion. Existe un conflicto que Subversion no sabe resolver entre la copia local y la existente en el repositorio. Tabla 4.apache. Existe una versi´n gratuita que se puede descargar desde http:// o subversion. La versi´n local es m´s actual que la o a existente en el repositorio. .

.3. o 5. Existen lenguajes de programaci´n. . es como se ha dicho. . Tipos de excepciones . . . 88 . . . En el cap´ ıtulo 6 veremos la t´cnica de Test unitarios para comprobar nuestro e software con objeto de eliminar el mayor n´mero posible de errores durante la u fase de desarrollo de nuestras aplicaciones. a o En Java existe un mecanismo de reacci´n ante situaciones an´malas muy pao o recido al de C++ con la gran diferencia de que el programador s´ que est´ obliı a gado a usarlo en aquellas situaciones susceptibles de provocar un error. . o . . pero el prograo o mador no est´ obligado a utilizarlo. . . . . . ya sean herramientas software o cualquier otro tipo de herramientas. o o 5. durante la ejecuci´n de o nuestras aplicaciones existir´n situaciones an´malas susceptibles de provocar un a o mal funcionamiento de nuestro software.2. . ¿Qu´ es una excepci´n? e o En Java. . . . Piensa por ejemplo en el caso en que un usuario intenta guardar un fichero en un directorio protegido contra escritura. . . . . . 5. . Piensa tambi´n en el acceso a una e 87 . . . No obstante. 87 . . . C´mo se gestiona una excepci´n . . como C++. Piensa o o o o en el ejemplo de la introducci´n en el que un usuario intenta guarda un fichero o en un directorio protegido contra escritura. .1. una excepci´n es una situaci´n an´mala en tiempo de ejecuci´n. que proporcionan un mecao nismo opcional de reacci´n frente a estas situaciones an´malas. . . . lo que conduce a la producci´n de c´digo m´s robusto frente a este tipo de fallos en o o a tiempo de ejecuci´n. .1. . 91 Introducci´n o Es evidente que lo deseable es que no se produzcan errores durante la ejecuci´n de un programa. ¿Qu´ es una excepci´n? .Cap´ ıtulo 5 Excepciones Contenidos 5. . .1. . Creaci´n de excepciones propias . . una opci´n. A todos nos provoca rechazo utilizar herramientas que o fallan. e o 5. . . . . . .1. . 88 .

1 la clase Exception es la o clase padre de este grupo de excepciones.1. de nuevo. Este es el tipo de excepciones que s´ estamos obligados a gestionar y para los que Java proporciona un ı potente mecanismo de gesti´n.. El tercer y ultimo tipo de excepciones est´ formado por el resto de situacio´ a nes que no son las anteriores. g e t M e s s a g e ( ) ) . p r i n t l n ( e . El c´digo donde se puede dar este tipo de situaciones es tan com´n o u que a˜adir m´s c´digo para gestionarlas sobrecargar´ terriblemente la esn a o ıa critura de nuestros programas. C´mo se gestiona una excepci´n o o Java proporciona un mecanismo de gesti´n de errores a trav´s de los bloques o e try. 5. o o o a intentar hacer un casting incompatible sobre una variable de tipo referencia.. como por ejemplo.1 la clase Error es la clase padre de todo este grupo de excepciones. a virtual Java tambi´n es una pieza de software y como tal est´ sujeta a e a fallos). El siguiente grupo de situaciones excepcionales son aquellas tan comunes c´mo intentar acceder a una posici´n inexistente de un array est´tico. En la Figura 5. // Q u i z ´ s s e p r o d u z c a un e r r o r d u r a n t e l a a lectura } catch ( FileNotFoundException e ) { // C´ digo de r e c u p e r a c i o n d e l e r r o r o ´ System . Excepciones de la propia m´quina virtual. 2. EXCEPCIONES posici´n fuera de un array est´tico. Todo este tipo de situaciones se producen o a en tiempo de ejecuci´n.88 CAP´ ITULO 5. // Q u i z a s e l f i c h e r o no e x i s t a ´ S t r i n g l i n e a = f ..catch. Tipos de excepciones En Java existen tres grandes grupos de excepciones dependiendo de su naturaleza: 1.1. por su naturaleza. intentar escribir en un directorio protegido contra escritura. o u t . son ajenos al programador y por lo tanto no estamos obligados a gestionarlos.. Estas excepciones causadas a por un mal funcionamiento de la propia m´quina virtual (S´ la m´quina a ı.finally. Pero quede el lector tranquilo. En la Figura 5. por lo que no es necesario gestionar este tipo de excepciones. En la Figura 5. tal y como se muestra en el siguiente Listado: 1 2 3 4 5 6 7 8 9 try { F i c h e r o f = a b r e F i c h e r o ( nombre ) . Si este tipo de errores se produce durante la ejecuci´n de nuestras aplicaciones puede ocurrir o que nuestra aplicaci´n se cierre y veamos un mensaje de error de la propia o m´quina virtual.2. Este tipo de errores. no o podemos evitar completamente que vayan a ocurrir. 3. y aunque podemos estar prevenidos contra ellas. l e e L i n e a ( ) . es extremadamente dif´ a ıcil encontrarse con un error de esta naturaleza. aunque si queremos siempre lo podemos hacer. 5.1 la clase RunTimeException es la clase padre de este grupo de excepciones. // Muestra una d e s c r i p c i ´ n d e l o error } catch ( IOException e ) { // C´ digo de r e c u p e r a c i o n d e l e r r o r o ´ } finally { .

la siguiente l´ ınea de c´digo 3 no se ejecutar´ la o ıa.} es una referencia del tipo del error correspondiente. que..} que se ejecutar´ con independencia de que se genere alguna de las excepciones gestioa nadas o no.1: Parte del ´rbol de jerarqu´ de las excepciones en Java..1: Ejemplo bloque try{.} el o los m´todos susceptibles de provocar e un error.. Es decir si existe el bloque finally{.. a ıa 10 11 12 13 // C´ digo com´ n o u } // O t r a s l´ n e a s de c ´ d i g o ı o System .2.} separados. La t´cnica para gestionar esta situaci´n es: e o 1.. o u t .}.. Recuerda. todo en Java es un objeto o y en particular los errores en tiempo de ejecuci´n son instancias de clases que o representan errores.. y una posible situaci´n an´mala es que el fichero no exista o o (FileNotFoundException) lo que puede provocar un error. si en la l´ ınea 2 se produce un error porque no se encontrase el fichero que se desea abrir. lleva una descripci´n sobre el error que se produjo. cada uno de los posibles errores que se pueden producir en el bloque try{..1. Encerrar en un bloque try{.} catch{...´ ´ 5. lo que tamı a bi´n puede provocar alg´n tipo de error de entrada/salida. o En el listado 5. p r i n t l n ( ” Aqu´ s i g u e l a ı e j e c u c i ´ n ”) . e u Antes de pasar a ver la t´cnica para gestionar estas situaciones an´malas. Atrapar en bloques catch{. 3.. En la l´ ınea 3 se est´ intentando leer una l´ a ınea desde el fichero que s´ est´ abierto..... entre otras cosas. e o f´ ıjate que cuando se produce un error.. Opcionalmente podemos definir un bloque finally{. o Listado 5. lo que recibe el bloque catch{.. .} su c´digo siempre o se ejecutara se produzca o no una excepci´n.} finally{.} En el ejemplo anterior.. COMO SE GESTIONA UNA EXCEPCION 89 Figura 5. el m´todo de la l´ e ınea 2 est´ intentando abrir a un fichero. 2.

t x t " ) . su referencia perdida al salir del m´todo y no podr´ ıa e ıamos cerrar el fichero. EXCEPCIONES ejecuci´n pasar´ directamente al bloque catch(FileNotFoundException e).}?. Despu´s de la gesti´n del error.2. como si o no se produce. Existen casos es los que nos interesa delegar la gesti´n de la excepci´n.. System . o o o La palabra reservada throws tambi´n se utiliza para lanzar excepciones proe pias tal y como vamos a ver en la Secci´n 5. ¿C´mo n o o o o e o indicamos que un m´todo no va a gestionar una determinada excepci´n?.2: Tanto la excepci´n FileNotFoundException como IOException se o delegan En el ejemplo del Listado 5. t x t " ) . close () . La l´ o ınea 6 nunca se ejecutar´ y el fichero queıa dar´ abierto. el bloque finally{. } Listado 5. ¿Qu´ sentido tiene incluir e el bloque finally{. Antes de contestar a esta pregunta veamos c´mo o podemos obviar la gesti´n de una excepci´n en el momento en que esta se o o produce y delegar su gesti´n en el m´todo que invoc´ al actual en la pila de o e o llamadas. a o 1 2 3 4 5 6 7 8 // E s t e m´ todo d e l e g a l a g e s t i o n de l a s e x c e p c i ´ n F i l e N o t F o u n d E x c e p t i o n e ´ o y IOException private void e j e c u t a ( ) throws F i l e N o t F o u n d E x c e p t i o n . se abandonar´ ıa la ejecuci´n del m´todo delegando la gesti´n de estas excepciones al m´todo o e o e que invoc´ a este (ejecuta()). tanto si se produce una excepci´n. que es quien delega la gesti´n de la excepci´n.3.} siempre se ejecutar´ y el fichero se a cerrar´ en cualquier caso. read ( ) .. la ejecuci´n seguir´ en la l´ e o o a ınea 13. o Ahora ya podemos contestar a la pregunta sobre la utilidad del bloque finally{..} observando el ejemplo del Listado 5. o ıa y tras su ejecuci´n al bloque finally de la l´ o ınea 10. int c a r a c t e r = 0 .3. la o o excepci´n ocurre en la definici´n de un determinado m´todo pero no queremos o o e a˜adir el c´digo de gesti´n de la excepci´n en la definici´n de ese m´todo. I O E x c e p t i o n { FileReader f r = null .. se produzca o no una excepci´n. fr . } finally { .} como el c´digo posterior a la gesti´n o o o de la excepci´n se ejecuta (c´digo en la l´ o o ınea 13). p r i n t l n ( " c a r a c t e r : " + c a r a c t e r ) . try { f r = new F i l e R e a d e r ( " f i c h e r o . Si tanto el c´digo en el bloque finally{. Si se produjese la excepci´n IOException en la l´ o ınea 4 durante el proceso de lectura.90 CAP´ ITULO 5.. c a r a c t e r = f r .. int c a r a c t e r = f r . ya que tenemos definido uno. con e o el uso de la palabra reservada throws como en el siguiente listado: 1 2 3 public void metodo ( ) throws F i l e N o t F o u n d E x c e p t i o n { // Aqu´ l a d e f i n i c i ´ n d e l m´ todo ı o e } En este caso estamos delegando la gesti´n de la excepci´n al m´todo que o o e llam´ a este otro. I O E x c e p t i o n { F i l e R e a d e r f r = new F i l e R e a d e r ( " f i c h e r o . o u t . 1 2 3 4 5 6 7 // E s t e m´ todo d e l e g a l a g e s t i o n de l a s e x c e p c i ´ n F i l e N o t F o u n d E x c e p t i o n e ´ o y IOException private void e j e c u t a ( ) throws F i l e N o t F o u n d E x c e p t i o n .. read ( ) ..

Creaci´n de excepciones propias o En el desarrollo de nuestras propias aplicaciones resulta interesante poder lanzar excepciones propias ante situaciones inesperadas.. Este String se podr´ recuperar o a en el bloque catch{.} de modo que tanto si se produjera una excepci´n de o tipo IOException como si fuera de tipo FileNotFoundException ambas provocar´ la ejecuci´n del bloque catch{IOException} ya que este bloque atrapa ıa o referencias de la clase padre y cualquier clase hija. o o 3. Gestionar la excepci´n como cualquier otra.3. F´ ıjate que el orden en los bloques try{. } } Listado 5..´ 5.1.} correspondiente como veremos m´s adelante..} finally{.} catch{. Piena sa qu´ ocurrir´ si se intercambiase el orden.. o El mecanismo para definir y lazar excepciones propias es el siguiente: 1.. 5. p r i n t l n ( " c a r a c t e r : " + c a r a c t e r ) ..2 7 3 o C " ) . Lanzar la excepci´n en las situaciones an´malas. o Al utilizar este mecanismo estamos creando excepciones que son tratadas del mismo modo que las excepciones predefinidas en Java.. o u t . la clase padre aparecer´ en el e ıa ıa primer bloque catch{. Supongamos que queremos generar una excepci´n o si se solicita una posici´n no v´lida dentro de nuestra aplicaci´n de la Agenda. a El siguiente paso es lanzar la excepci´n en caso de producirse una situaci´n o o an´mala. Definir la nueva clase que representa a nuestra excepci´n.. CREACION DE EXCEPCIONES PROPIAS 9 10 11 12 91 System . o 2. como en el Listado 5.4: 1 2 3 4 5 public c l a s s T e m p e r a t u r a N o V a l i d a E x c e p t i o n extends E x c e p t i o n { public T e m p e r a t u r a N o V a l i d a E x c e p t i o n ( ) { super ( " L a t e m p e r a t u r a n o p u e d e s e m e n o r q u e . i f ( f r != n u l l ) f r .} va desde el m´s espec´ a ıfico (FileNotFoundException) al m´s general (IOException). } } Listado 5. y por lo tanto sobre ellas es v´lido todo lo e a que aprendimos sobre herencia en el cap´ ıtulo 3. Recuerda. Java proporciona un mecanismo para definir nuevas excepciones y lanzarlas en los casos en los que se produzcan situaciones an´malas. tal y como se muestra en el Listado 5. c l o s e ( ) .4: Definici´n de una excepci´n propia o o F´ ıjate que el constructor por defecto llama a super del padre con un String que es una descripci´n del error que ha ocurrido. o a o Lo primero que debemos hacer es definir la clase que representa a nuestra nueva excepci´n. las excepciones tambi´n son instancias de objetos.} Otro detalle importante es el orden de los errores que se atrapan en los bloques catch{.. Veamos cada uno de estos pasos con un ejemplo...3..3: En este caso el fichero siempre se gracias al uso del bloque finally{..5 : o .}.. Compara el orden del ejemplo del Listado 5. El detalle que debemos tener en cuenta es que nuestra excepci´n o o debe ser hija de la clase Exception.

g e t M e s s a g e ( ) ) . 0 ∗ c e l s i u s + 3 2 . return 9 . o u t . La segunda es que para o lanzar la excepci´n utilizamos la palabra reservada throw y creamos una nueva o instancia de la excepci´n con new. p r i n t l n ( c e l s i u s + " \ t " + f h a r e n h e i t + " \ t " + reamur ) . } } Listado 5. EXCEPCIONES 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public c l a s s C o n v e r s o r T e m p e r a t u r a s { private f i n a l double CERO ABSOLUTO = − 2 7 3 . tal a y como se muestra en el Listado 5..}. } catch ( T e m p e r a t u r a N o V a l i d a E x c e p t i o n e ) { System . a Nuestra excepci´n se gestiona como cualquier otra ya definida en el paquete o est´ndar de Java. mediante el bloque try{. 1 5 .} finally{. return 4 . 0 / 5 . c e l s i u s A R e a m u r ( c e l s i u s ) .. o . c e l s i u s < 1 0 1 . } } Listado 5. la primera es que el m´todo e desde el que se lanza la excepci´n indica que va a hacerlo con el uso de la palabra o reservada throws seguida del nombre de la excepci´n. } public double c e l s i u s A F h a r e n h e i t ( double c e l s i u s ) throws TemperaturaNoValidaException { i f ( c e l s i u s < CERO ABSOLUTO) throw new T e m p e r a t u r a N o V a l i d a E x c e p t i o n ( ) . En la l´ ınea 7 de este listado se muestra c´mo recuperar el texto descriptivo de la excepci´n que proporcionamos en la o o definici´n de la clase TemperaturaNoValidaException. o u t .6: Definici´n de una excepci´n propia o o Lecturas recomendadas El cap´ ıtulo 8 de la referencia [2] presenta todos los detalles de la gesti´n o de excepciones y c´mo crear excepciones propias... 1 2 3 4 5 6 7 8 9 f o r ( i n t c e l s i u s = 0 .} catch{.6.92 CAP´ ITULO 5. System . p r i n t l n ( e . Un m´todo util para o e ´ recuperar toda la traza de ejecuci´n de nuestro programa hasta el momento o en el que se produzco la excepci´n es printStackTrace() definido en la clase o Throwable que es la clase de la que heredan todas las excepciones en Java. public C o n v e r s o r T e m p e r a t u r a s ( ) { super ( ) . 0 . celsiusAFharenheit ( c e l s i u s ) . 0 / 5 .5. } public double c e l s i u s A R e a m u r ( double c e l s i u s ) throws TemperaturaNoValidaException { i f ( c e l s i u s < CERO ABSOLUTO) throw new T e m p e r a t u r a N o V a l i d a E x c e p t i o n ( ) .. 0 ∗ c e l s i u s . reamur = c o n v e r s o r ..5: Definici´n de una excepci´n propia o o Cabe resaltar un par de cosas del Listado 5. recuerda que una excepci´n al fin y al cabo o o no es m´s que una instancia de una clase. c e l s i u s += 5 ) { try { fharenheit = conversor .

2. Cobertura de las pruebas . . 101 6. e 94 6. . es un requerimiento. a 93 . . 98 6. y confiamos que en el resto de casos nuestro c´digo o est´ libre de errores. . . . . . . . La anotaci´n @Test . EclEmma y su plug-in para Eclipse . . . . . . o e o El siguiente paso que usualmente se suele dar es comprobar la validez del c´digo realizando pruebas. . . Las anotaciones @Before y @After . a e paradojas de la vida. . . . . . 96 o 6. Sabemos c´mo definir clases.1. 95 6. nuestro c´digo est´ plagado de errores que no hemos sido capaces de n o a detectar y que tarde o temprano saldr´n a la luz sumi´ndonos en la oscuridad. . 103 Introducci´n o Llegados a este punto ya somos capaces de escribir aplicaciones Java utilizando los principios de la POO. . . . . .2.1. .1. . .1. .2. Pruebas con bater´ de datos de entrada . . valores de los que conocemos o cual es la salida esperada. . . Test Suites . . . . por defecto. probamos unos o cuantos valores de entrada en nuestra aplicaci´n. .2. 95 o 6. . . .2. . A veces. . . . 100 ıa 6. . . . . . en todo desarrollo de proyectos o inform´ticos. . . . Las anotaciones @BeforeClass y @AfterClass . . . .3. 102 6. .4. Y en este momento es cuando la confianza se convierte en e enga˜o. . . . .3. Incluso o somos capaces de controlar las situaciones an´malas que pueden darse durante o la ejecuci´n de nuestras aplicaciones a trav´s de la gesti´n de excepciones.2. . . . . ¿Qu´ son las pruebas unitarias? . .2. . . 99 6. . . . estas pruebas son caseras.1. . Pruebas unitarias con JUnit .6. .Cap´ ıtulo 6 Pruebas unitarias con JUnit Contenidos 6.3. . . . .2. Creaci´n de clases de prueba . . . . . . . . . .5. . . . . . La primera idea que debemos fijar es que hacer pruebas de c´digo no debe o ser una opci´n. Principios FIRST para el dise˜o de pruebas unitarias 94 n 6. . Ejecutar varias clases de prueba. como utilizar la herencia o o la composici´n para ampliar el comportamiento de nuestras clases. . .

El resultado de una prueba debe ser siempre el mismo. Independent : Una prueba no puede depender de otras. Self-validating : S´lo hay dos posibles resultados de una prueba: ((La prueba o pas´ con ´xito)) o ((La prueba fall´)). resulta imposible comprobar esta clase de modo aislado.1. ¿Qu´ son las pruebas unitarias? e Las pruebas unitarias se realizan sobre una clase. a o En este cap´ ıtulo se va a mostrar c´mo utilizar una herramienta para como probar c´digo. o .1. 6. son tan importantes como el c´digo que se est´ probando o o a y por lo tanto debemos dedicarles el mismo empe˜o que al desarrollo del c´digo n o de nuestra aplicaci´n. aunque existen t´cnicas (como los Mock Objects) que minimizan estas e dependencias. Si las pruebas cono o a sumen demasiado tiempo acabaremos por no hacerlas. no se va a mostrar c´mo escribir c´digo que se pueda a o o probar f´cilmente.1. o 6. n Cada una de las letras de esta palabra inglesa est´ relacionada con un concepto. y que la prueba de la clase se base en el resultado que se recupera de la base de datos. a Ve´moslos: a Fast : La ejecuci´n del c´digo de pruebas debe ser r´pida. o e o Timely : Las pruebas han de escribirse en el momento de escribir el c´digo. por aburrimiento o falta de tiempo acabaremos por no hacerlas. o n o y lo que es m´s importante. Si son manuales. Principios FIRST para el dise˜ o de pruebas unitan rias Cuando se dise˜an pruebas unitarias es importante seguir los principios FIRST. Este o requisito a veces no se cumple. piensa en el c´digo de una clase que accede a o una base de datos. Cada prueba debe ser unitaria. Las pruebas automatizadas forman parte del c´digo del proyecto. en la secci´n de referencias de este cap´ a o ıtulo se dan algunos t´ ıtulos que son de lectura obligada a todo desarrollador que quiera poner en pr´ctica la prueba de c´digo en sus proyectos. Esta excelente herramienta es JUnit. si no automatizadas. debe poder realizarse de modo aislado. independientemente del resto de clases de la aplicaci´n. PRUEBAS UNITARIAS CON JUNIT La segunda idea que debemos fijar es que las pruebas de c´digo no deben o ser manuales. o En este cap´ ıtulo no se va a mostrar c´mo dise˜ar buenas pruebas de c´digo.94 CAP´ ITULO 6. para probar su comportamiento de modo aislado. Repetable : Las pruebas se deben poder repetir en cualquier momento y la cantidad de veces que sea necesario. y o no al final de toda la fase de desarrollo 1 1 La metodolog´ de desarrollo Test Driven Development (TDD) lleva este principio al ıa inicio del proceso de desarrollo de tal modo que las pruebas de c´digo se escriben antes que o el propio c´digo que se intenta probar.

y aunque son c´modos de o o utilizar. a a Cabe destacar varios puntos de este Listado: 1. PRUEBAS UNITARIAS CON JUNIT 95 6. F´ ıjate en el uso del import static de la l´ ınea 3. Un import static me permite utilizar e a todos los m´todos static de una clase sin necesidad de anteponer al e m´todo el nombre de la clase 2 . que en nuestro caso es ConversorTemperaturas. j u n i t .2. en la parte inferior de esta ventana pulsamos Browse y seleccionamos la clase que deseamos probar. 3. Pruebas unitarias con JUnit JUnit es una herramienta para realizar pruebas unitarias automatizadas.6. import s t a t i c o r g . Por defecto... introducimos el nombre para la clase de prueba y su paquete. y que la signatura de ambos es public void nombreDelMetodo(). e 2. en nuestro caso vamos a seleccionar celsiusAFharenheit(double) y celsiusAReamur(double) y pulsamos Finish. JUnit est´ integrada en Eclipse. como fail. Los m´todos de prueba deben ser p´ blicos no e u retornar ning´n valor y su lista de argumentos debe estar vac´ u ıa. en la parte supea a rior seleccionamos New JUnit 4 test. en la nueva ventana veremos que se nos ofrece la posibilidad de seleccionar los m´todos que queremos e probar. 6.2. La clase de prueba que se crear´ aua tom´ticamente ser´ la que se muestra en el Listado 6.2. en la ventana de di´logo que se abrir´ seleccionamos Java → JUnit → a a JUnit Test Case. A s s e r t . y pulsamos Next. En general. ∗ . pueden provocar confusi´n en el programador. T e s t . e 4. import o r g . j u n i t . Creaci´n de clases de prueba o Para crear una clase de prueba en Eclipse seleccionamos File → New → Other. a 2 Los . public c l a s s T e s t C o n v e r s o r T e m p e r a t u r a s { static import se introdujeron en la versi´n 5 de Java.".1. F´ ıjate que sobre cada uno de los m´todos de prueba aparece la anotaci´n e o @Test que indica al compilador que es un m´todo de prueba. el uso de JUnit es un caso. se abrir´ una nueva ventana de di´logo. y por comodidad. Eclipse facilita la creaci´n de pruebas unitarias. o 1 2 3 4 5 6 7 package t e s t . ya que o al no aparecer el nombre de la clase tendremos la duda de si el m´todo pertenece a la clase e actual o a un clase de la que se ha hecho un static import. no es necesario descargarse ning´n paquete ni instalar a u un nuevo plug-in para utilizarla.1. una para cada m´todo e e que seleccionamos sobre la clase a probar. cada uno de los m´todos de prueba tiene una llamada a e fail("Mesaje con descripci´n. o Para mostrar con un ejemplo c´mo se escriben pruebas unitarias de o c´digo con JUnit vamos a utilizar las clases ConversorTemperaturas y o TemperaturaNoValidaException que vimos en el cap´ ıtulo anterior.. es util para no tener ´ que incluir el nombre de la clase Assert cuando utilizamos alguno de sus m´todos est´ticos. Observa que se han creado dos m´todos de prueba. el uso de los static import est´ desaconsejado.

1 2 3 4 5 @Test public void t e s t C e l s i u s A R e a m u r ( ) throws T e m p e r a t u r a N o V a l i d a E x c e p t i o n { C o n v e r s o r T e m p e r a t u r a s c o n v e r s o r = new C o n v e r s o r T e m p e r a t u r a s ( ) . Escribamos el c´digo para la segunda de las pruebas tal y o como se muestra en el Listado 6. F´ ıjate que tambi´n hemos a˜adido e n throws TemperaturaNoValidaException para indicar que no queremos gestionar esta posible excepci´n en el c´digo del m´todo de prueba. La anotaci´n @Test o Como ya se ha dicho. } @Test public f i n a l void t e s t C e l s i u s A R e a m u r ( ) { f a i l ( " Not yet implemented " ) . Este m´todo comprueba que la diferencia entre el e valorEsperado y el valorObtenido es menor que error. la anotaci´n @Test sirve para indicar que un determinado o m´todo es un m´todo de prueba.2: Un m´todo de prueba.2. la prueba. 0) .1: C´digo generado autom´ticamente por Eclipse para una clase de o a prueba. e Lo primero que hacemos en el m´todo de prueba es crear una instancia e de la clase ConversorTemperaturas.3: Un segundo m´todo de prueba. as ser tEq ual s (32 . Vamos a escribir el primer c´digo de prueba e e o tal y como se muestra en el Listado 6.2. valorObtenido. } Listado 6. 6.96 8 9 10 11 12 13 14 15 16 17 18 19 CAP´ ITULO 6. en este caso estamos asea e verando que la diferencia entre el valor que devuelve la llamada al m´todo e celsiusAReamur(0) y el valor 0 es cero. PRUEBAS UNITARIAS CON JUNIT @Test public f i n a l void t e s t C e l s i u s A F h e r e n h e i t ( ) { f a i l ( " Not yet implemented " ) . que en nuestro caso es Runs: 2/2 Errors: 0 Failures: 0 que nos . e De modo an´logo al primer m´todo de prueba. En nuestro caso. } Listado 6. Para ejecutar las pruebas desde Eclipse pulsa el bot´n derecho del rat´n o o sobre la clase de prueba y en el men´ emergente selecciona la opci´n Run As → u o JUnit Test. a s s e r t E q u a l s ( 0 . y despu´s utilizar el m´todo assertEquals( e e valorEsperado. 0) .3. Si es as´ se ha pasado ı. celsiusAReamur ( 0 ) . celsiusAFharenheit (0) .2. o o e 1 2 3 4 5 @Test public void t e s t C e l s i u s A F h a r e n h e i t ( ) throws TemperaturaNoValidaException { C o n v e r s o r T e m p e r a t u r a s c o n v e r s o r = new C o n v e r s o r T e m p e r a t u r a s ( ) . } } Listado 6. c o n v e r s o r . se est´ aseverando a que la diferencia entre el valor que devuelve el m´todo celsiusAFharenheit(0) e y el valor 32 es cero. ver´s que se abre una nueva vista con el resultado de la ejecuci´n a o de las pruebas. conversor . error). de lo contrario la prueba falla.

cosa que ser´ indicativa de que algo ha ido mal ya lo que a a intentamos probar es que la excepci´n s´ que se produce.6. } catch ( T e m p e r a t u r a N o V a l i d a E x c e p t i o n e ) { } } Listado 6. Si ejecutamos de nuevo las pruebas veremos que todas ellas pasan. 0). c o n v e r s o r . en este caso obtendremos un fallo que nos informar´ que el valor esperado de la prueba era 0 mientras que el valor obtenido a es 32. y ejecutemos de nuevo la prueba. ¿Y si nuestra prueba o pasa precisamente si se genera la excepci´n? Para ello basta con a˜adir el atrio n buto expected=TemperaturaNoValidaException. A˜adamos otro m´todo de prueba que genere un error.5. ¿Cual es la diferencia entre un fallo y un error en el contexto de las pruebas unitarias con JUnit?. Si no se produce la excepci´n en la l´ o ınea 5. o ı 1 2 3 4 5 6 7 8 9 @Test public void t e s t T e m p e r a t u r a N o V a l i d a d F a h r e n h e i t ( ) { C o n v e r s o r T e m p e r a t u r a s c o n v e r s o r = new C o n v e r s o r T e m p e r a t u r a s ( ) . try { c o n v e r s o r . Generemos un fallo de o o o modo artificial para ver el resultado.2.class a la anotaci´n @Test o quedando de este modo @Test(expected=TemperaturaNoValidaException. tal y como se muestra en el Listado 6. conversor. ninguna de ellas a provocado un error y ninguna de ellas a provocado un fallo. a a e a ..0. Si la excepci´n se produce al ejecutarse la l´ o ınea 5. que a es lo que esperamos.celsiusAFharenheit(0)..4. PRUEBAS UNITARIAS CON JUNIT 97 indica que se han realizado 2 pruebas. 1 2 3 4 public void t e s t T e m p e r a t u r a N o V a l i d a F h a r e n h e i t ( ) throws TemperaturaNoValidaException { C o n v e r s o r T e m p e r a t u r a s c o n v e r s o r = new C o n v e r s o r T e m p e r a t u r a s ( ) . o Esta vez el m´todo est´ etiquetado unicamente con @Test.5: Un m´todo de prueba que genera un error.class). 0). conversor. celsiusAFharenheit(0). e Al ejecutar de nuevo las pruebas esta vez obtendremos la excepci´n La temo peratura no puede ser menor que -273o C. c e l s i u s A F h a r e n h e i t ( −400) . Un fallo es una aseveraci´n que no se cumple. y detr´s de la l´ e a ´ a ınea de c´digo que esperamos que produzca la excepci´n escribimos fail("Para o o temperaturas por encima de -273 la prueba debe pasar. para ver la diferencia n e con un fallo. ya que e es m´s f´cil interpretar qu´ es lo que se est´ intentando probar. la ejecuci´n de la prueba continuar´ en o a el bloque catch (TemperaturaNoValidaException e) y la prueba pasar´. cambiemos la l´ ınea assertEquals(32. es decir. ¿Y si lo que queremos es precisamente comprobar que se lanza la excepci´n?. c e l s i u s A F h a r e n h e i t ( −400) . .4: Un m´todo de prueba que genera un error. f a i l ( " Para t e m p e r a t u r a s por encima de -273 la prueba debe pasar .) a y la prueba no pasar´. se ejecutar´ la sentencia fail(."). } Listado 6. un o error es una excepci´n durante la ejecuci´n del c´digo. por esta otra assertEquals(0. e Este segundo m´todo de prueba de excepciones es el recomendado. Otra t´cnica que no utiliza el atributo expected de la anotaci´n @Test pae o ra comprobar que se produce una excepci´n es la mostrada en el Listado 6. " ) .

o En nuestro caso. public c l a s s T e s t C o n v e r s o r T e m p e r a t u r a s 2 { private C o n v e r s o r T e m p e r a t u r a s c o n v e r s o r . 0) . Las anotaciones @Before y @After Si revisas el c´digo de los tres m´todos de prueba anteriores ver´s que lo primero o e a que hacemos es crear una instancia de la clase ConversorTemperaturas. } } Listado 6. C o n v e r s o r T e m p e r a t u r a s . celsiusAReamur ( 0 ) . c e l s i u s A F h a r e n h e i t ( −400) . Por lo tanto. import o r g .3. } @Test public void t e s t C e l s i u s A F h a r e n h e i t ( ) throws TemperaturaNoValidaException { as ser tEq ual s (32 . c l a s s ) public void t e s t T e m p e r a t u r a N o V a l i d a F h a r e n h e i t ( ) throws TemperaturaNoValidaException { c o n v e r s o r . Todos los m´todos que est´n anotados con @Before se ejecutar´n e e a antes de cada uno de los m´todos de prueba y todos los m´todos que est´n e e e anotados con @After se ejecutar´n despu´s de cada uno de los m´todos de a e e . ∗ . import c o n v e r s o r . conversor . puede haber m´s de un m´todo anotado con alguna de estas a e anotaciones. j u n i t . A f t e r . JUnit nos proporciona un mecanismo para extraer el c´digo que se repite en todos o los m´todos. A s s e r t . j u n i t . la clase de prueba quedar´ tal y como se muestra en el ıa Listado 6. 0) .6: Uso de las anotaciones @Before y @After. j u n i t . } @Test ( e x p e c t e d=T e m p e r a t u r a N o V a l i d a E x c e p t i o n . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import s t a t i c o r g . PRUEBAS UNITARIAS CON JUNIT 6. } @Test public void t e s t C e l s i u s A R e a m u r ( ) throws T e m p e r a t u r a N o V a l i d a E x c e p t i o n { a s s e r t E q u a l s ( 0 . Por su e a e lado. } @After public void d e s t r u y e C n v e r s o r T e m p e r a r t u r a s ( ) { conversor = null . @Before public void c r e a C o n v e r s o r T e m p e r a t u r a s ( ) { c o n v e r s o r = new C o n v e r s o r T e m p e r a t u r a s ( ) . si tenemos tres a e m´todos de prueba ser´ ejecutado antes de cada uno de los tres m´todos. Las anotaciones @Before y @After las puedes utilizar tantas veces como te sea necesario. import c o n v e r s o r . import o r g . j u n i t . c o n v e r s o r . a trav´s de las e e anotaciones @Before y @After. celsiusAFharenheit (0) . B e f o r e . si anotamos un m´todo con @After ser´ ejecutado despu´s de la ejecuci´n e a e o de cada uno de los m´todos de prueba. import o r g .98 CAP´ ITULO 6.2. Si anotamos un m´todo con @Before su c´digo e o ser´ ejecutado antes de cada uno de los m´todos de prueba.6. y que debe ejecutarse antes de cualquiera de ellos. T e s t . T e m p e r a t u r a N o V a l i d a E x c e p t i o n . podemos usar la anotaci´n e o @Before para iniciar todas las infraestructuras necesarias a la ejecuci´n de las o pruebas y la anotaci´n @After para limpiar estas infraestructuras.

c e l s i u s A F h a r e n h e i t ( −400) . public c l a s s T e s t C o n v e r s o r T e m p e r a t u r a s 3 { private s t a t i c C o n v e r s o r T e m p e r a t u r a s c o n v e r s o r . celsiusAFharenheit (0) . A f t e r C l a s s . c l a s s ) public void t e s t T e m p e r a t u r a N o V a l i d a F h a r e n h e i t ( ) throws TemperaturaNoValidaException { c o n v e r s o r . B e f o r e C l a s s . c o n v e r s o r . import o r g . los atributos a los que acceden tambi´n deben ser static. . 99 6. los m´todos e anotados con @BeforeClass y @AfterClass deben ser ambos static y por lo tanto. F´ ıjate que la clase que estamos probando ConversorTemperaturas no tiene estado. a s s e r t E q u a l s . y por lo tanto el resultado de las llamadas a sus m´todos es independiente del orden en el que se hagan. import o r g .2. } @AfterClass public s t a t i c void d e s t r u y e C n v e r s o r T e m p e r a r t u r a s ( ) { conversor = null .7: Uso de las anotaciones @BeforeClass y @AfterClass. conversor . celsiusAReamur ( 0 ) . } @Test ( e x p e c t e d=T e m p e r a t u r a N o V a l i d a E x c e p t i o n . import c o n v e r s o r . si anotamos un m´todo de una clase de prueba con e @AfterClass el m´todo ser´ ejecutado una unica vez despu´s de haberse ejecue a ´ e tado todos los m´todos de prueba.6. import c o n v e r s o r . T e m p e r a t u r a N o V a l i d a E x c e p t i o n . T e s t . @BeforeClass public s t a t i c void c r e a C o n v e r s o r T e m p e r a t u r a s ( ) { c o n v e r s o r = new C o n v e r s o r T e m p e r a t u r a s ( ) . e 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 import s t a t i c o r g . j u n i t . Por otro lado. A s s e r t . 0) . tal y como e vimos en 2.4. 0) . tal y como se muestra en el Listado 6. Las anotaciones @BeforeClass y @AfterClass Podemos mejorar un poco m´s nuestra clase de prueba con el uso de dos nuevas a etiquetas @BeforeClass y @AfterClass.7. por lo e que no es necesario crear una instancia nueva antes de cada una de las pruebas. C o n v e r s o r T e m p e r a t u r a s .2. j u n i t . si no que la misma instancia nos sirve para las tres pruebas.6. PRUEBAS UNITARIAS CON JUNIT prueba. Si anotamos un m´todo de una clase de prueba con @BeforeClass ese m´toe e do se ejecutar´ una unica vez antes de la ejecuci´n de cualquier m´todo de a ´ o e prueba. } @Test public void t e s t C e l s i u s A R e a m u r ( ) throws T e m p e r a t u r a N o V a l i d a E x c e p t i o n { a s s e r t E q u a l s ( 0 . } @Test public void t e s t C e l s i u s A F h a r e n h e i t ( ) throws TemperaturaNoValidaException { as ser tEq uals (32 . F´ ıjate en el importante detalle que aparece en el Listado 6. import o r g . } } Listado 6.7. j u n i t . j u n i t .

Si queremos escribir una nueva prueba para otro tr´ de valores es ıo tedioso crear un m´todo s´lo para ´l. . double e r r o r ) { this . 3 2 . C o l l e c t i o n . double reamur . this . 2 4 . 0 } .0 . double f h a r e n h e i t . En el Listado 6. import c o n v e r s o r . u t i l . Parameterized . 122. 0 . junit junit junit junit junit junit . La clase de prueba ha de declarar un atributo por ıas cada uno de los par´metros de la prueba. // { c e l s i u s . . org . AfterClass . fharenheit = fharenheit . BeforeClass . 4 0 . 0 } .0 . . j u n i t .2. Test . C o n v e r s o r T e m p e r a t u r a s . 0 . {30 . 0. 5 9 . 0 .class) indicando que va a ser utilizada para realizar bater´ de pruebas.100 CAP´ ITULO 6. 0 . this . 0 } . 0 . } @Parameters public s t a t i c C o l l e c t i o n <O b j e c t [ ] > d a t o s ( ) { return A r r a y s . 0 . runners . a s L i s t (new O b j e c t [ ] [ ] { { 0 . r u n n e r . 7 2 . {90 . Pruebas con bater´ de datos de entrada ıa Cada uno de los m´todos de prueba de los ejemplos anteriores utiliza un tr´ de e ıo datos. ∗ . Finalmente necesitamos definir un m´todo a e que devuelva la colecci´n de datos a probar anotado con @Parameters . private s t a t i c C o n v e r s o r T e m p e r a t u r a s c o n v e r s o r . } @BeforeClass public s t a t i c void i n i c i a C o n v e r s o r ( ) { c o n v e r s o r = new C o n v e r s o r T e m p e r a t u r a s ( ) . import c o n v e r s o r . runners . org . reamur = reamur . cada uno de los m´todos de prueba ser´ llamado para cada una de las e a tuplas de valores de prueba. @RunWith ( P a r a m e t e r i z e d . 0 . 0 . c e l s i u s = c e l s i u s . JUnit proporciona un mecanismo para e o e probar bater´ de valores en vez de unicamente tr´ aislados. public T e s t C o n v e r s o r T e m p e r a t u r a s 4 ( double c e l s i u s . 0 . org . private double reamur . A r r a y s . PRUEBAS UNITARIAS CON JUNIT 6. T e m p e r a t u r a N o V a l i d a E x c e p t i o n .5. u t i l . import j a v a . e r r o r = e r r o r . ıas ´ ıos Lo primero que debemos hacer es anotar la clase de prueba con @RunWith(Parameterized.0} }) . 1 2 . t h i s . De este o modo. . private double e r r o r . org . 0 . valor real y error para comprobar cada uno de los casos de prueba. 8 6 .8 se muestra un ejemplo de clase de prueba para una bater´ ıa de pruebas sobre la clase ConversorTemperaturas. 0 . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import s t a t i c o r g . . import j a v a . {15 . Parameters . Parameterized . 0 } . 0 . A s s e r t . {50 . } @AfterClass error} . RunWith . c l a s s ) public c l a s s T e s t C o n v e r s o r T e m p e r a t u r a s 4 { private double c e l s i u s . f h a r e n h e i t . org . valor esperado. 194. private double f h a r e n h e i t . import import import import import import org . 0 . y un constructor con tantos argumena tos como par´metros en cada prueba. 0 . reamur .

S u i t e . 2. Declarar un atributo en la clase por cada par´metro de prueba. r u n n e r .8: Ejemplo de definici´n de una clase que realiza una bater´ de o ıa pruebas. o Por lo tanto. o al menos algunas de ellas sin tener que ejecutarla cada clase de modo independiente? Para ello existe un mecanismo en JUnit llamado Test Suites.2. } @Test public void t e s t C e l s i u s A F h a r e n h e i t ( ) throws TemperaturaNoValidaException { assertEquals ( fharenheit . a 3.class). estos son los pasos para definir una clase que ejecuta bater´ de pruebas: ıas 1.2. es tener varias clases de prueba ya que a veces u no tiene sentido una unica clase donde se realicen todas las pruebas. tal y como se muestra en el Listado 6. celsiusAFharenheit ( c e l s i u s ) . j u n i t . } @Test public void t e s t C e l s i u s A R e a m u r ( ) throws T e m p e r a t u r a N o V a l i d a E x c e p t i o n { a s s e r t E q u a l s ( reamur . import o r g . a 4. como por ejemplo comprobar que se produce una excepci´n. lo que JUnit hace en el caso de las a bater´ de pruebas es crear una instancia de la clase de prueba a partir del ıas constructor con tantos argumentos como par´metros en cada una de las tuplas a de prueba. Internamente y de modo esquem´tico. j u n i t .6. e r r o r ) . quiz´s tengas alg´n caso de prueba a u sobre el que no tenga sentido realizar pruebas parametrizadas. que no son m´s que agrupaciones de clases de prueba que se ejecutan a una tras otra. r u n n e r s . Definir un constructor con tantos argumentos como par´metros de prueba. S u i t e .9. De modo resumido. S u i t e C l a s s e s . 1 2 3 4 import o r g . Piensa ´ por ejemplo en las pruebas parametrizadas. si tenemos varias clases de prueba. conversor . y seguidamente llama a cada uno de los m´todos de prueba. c e l s i u s A R e a m u r ( c e l s i u s ) . import o r g . error ) .6. e 6. c o n v e r s o r . RunWith . ¿C´mo podemos ejecutar o todas las pruebas. Definir un m´todo que devuelva una colecci´n con todas las tuplas de e o prueba. r u n n e r s . Test Suites Lo com´n. y anotarlo con Parameters. . Anotar la clase de prueba con @RunWith(Parameterized. j u n i t . como hemos visto. } } Listado 6. B´sicamente lo que hacemos es anotar una clase para que JUnit la reconozca a como una suite de pruebas y con otra anotaci´n a˜adimos a esta clase todas las o n clases de prueba que nos interese ejecutar. PRUEBAS UNITARIAS CON JUNIT 48 49 50 51 52 53 54 55 56 57 58 59 60 61 101 public s t a t i c void e l i m i n a C o n v e r s o r ( ) { conversor = null . Ejecutar varias clases de prueba.

.3. TestConversorTemperaturas3 . Puedes cubrir el 100 % de la ejecuci´n o o o del c´digo con casos triviales que nunca fallar´n y no sacar´n a la luz los posibles o a a errores de tu c´digo. Cobertura de las pruebas Una duda que nos surge al realizar pruebas unitarias es la cantidad de l´ ıneas de c´digo que han cubierto las pruebas. } @Test p u b l i c v o i d m as V i e jo E l Se g u nd o ( ) { P e r s o n a p r i m e r a = new P e r s o n a ( ) . Los m´todos de prueba cubren el 100 % del c´digo del m´todo que e o e se est´ probando pero. p r i m e r a . class }) public c l a s s A l l T e s t s { } Listado 6. setEdad ( 1 0 0 ) . segunda .10 te muestra un m´todo a probar y un par de m´todos e e de prueba. De este modo bien podemos ejecutar una unica clase de prueba para probar ´ el funcionamiento correcto de una clase en particular de todas las que forman nuestro proyecto. edad < segunda .102 5 6 7 8 9 10 11 12 13 CAP´ ITULO 6. } // T r e s m´ todos de prueba e @Test p u b l i c void masViejoElPrimero ( ) { P e r s o n a p r i m e r a = new P e r s o n a ( ) . ni mucho menos.9: Ejemplo de una suite de pruebas Test Suite. P e r s o n a segunda ) { i f ( p r i m e r a . o Para que veas con claridad la diferencia entre cobertura de c´digo y pruebas o exhaustivas el Listado 6. 0 ) . class . c l a s s ) @SuiteClasses ({ TestConversorTemperaturas . a s s e r t E q u a l s ( −1 . o bien podemos ejecutar toda la suite de clases de prueba para probar todo nuestro proyecto. ¿Ha quedado alg´n fragmento de c´digo o u o que no se ha ejecutado ni una sola vez para todas las pruebas? ¿C´mo podemos o saberlo?. PRUEBAS UNITARIAS CON JUNIT @RunWith ( S u i t e . class . setEdad ( 1 0 0 ) . setEdad ( 5 0 ) . Pero no caigas en el enga˜o de pensar que por cubrir n con pruebas el 100 % del c´digo est´s cubriendo todos los casos posibles de la o a ejecuci´n de ese c´digo. P e r s o n a segunda = new P e r s o n a ( ) . o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // M´todo que s e va a p r o b a r e p u b l i c i n t quienEsMayor ( P e r s o n a p r i m e r a . ¿Qu´ pasa si alguna de las referencias que se pasan al a e m´todo de prueba es null? Evidentemente el m´todo que se est´ probando e e a contiene un error que no ser´ descubierto por las pruebas aunque estas est´n a e cubriendo el 100 % del c´digo. 6. p r i m e r a . edad ) r e t u r n −1. e l s e return 0. Lo ideal es que nuestras pruebas cubran el 100 % del c´digo de la clase o que estamos probando. segunda ) . segunda . TestConversorTemperaturas4 . P e r s o n a segunda = new P e r s o n a ( ) . edad ) r e t u r n 1 . edad > segunda . class . TestConversorTemperaturas2 . setEdad ( 5 0 ) . i f ( p r i m e r a . quienEsMayor ( p r i m e r a .

si no ha sido o cubierta. p r i m e r a . La referencia [5] presenta de modo exhaustivo las o pruebas de c´digo que se han de realizar para garantizar que se cubre el 100 % o de los posibles caminos de ejecuci´n. setEdad ( 5 0 ) . } @Test p u b l i c v o i d mismaEdad ( ) { P e r s o n a p r i m e r a = new P e r s o n a ( ) . la cobertura de nuestras pruebas unitarias. o 6. Aunque los o . segunda ) . de autores espa˜oles. Una de esas herramientas. COBERTURA DE LAS PRUEBAS 24 25 26 27 28 29 30 31 32 33 34 103 a s s e r t E q u a l s ( 1 . se abrir´ una nueva vista de nombre Coverage en la que se te a mostrar´ todos los resultados de la cobertura de la prueba. una tabla con el porcentaje de l´ ıneas de c´digo cubiertas por la prueba. de cada una de las l´ ıneas de c´digo de la clase que se est´ probando o a se colorear´ su fondo en verde. EclEmma y su plug-in para Eclipse Afortunadamente existen excelentes herramientas que miden. amarilla. si ha sido cubierta s´lo parcialmente. de modo que se contemplan todos los posibles casos de fallo de nuestro c´digo. quienEsMayor ( p r i m e r a . o roja.org/. aunque no la unica es Ecl-Emma de la que existe un plug-in para Eclipse y cuya p´gina ´ a web es http://www. Si pulsas este bot´n cuando est´ seleccionada una o o a clase de prueba. quienEsMayor ( p r i m e r a .6.3. a Una vez instalado este plugin te aparecer´ un nuevo bot´n en Eclipse a la a o izquierda del bot´n ejecutar. o Lecturas recomendadas. pero siendo la direcci´n del o o plug-in la que se indica en la p´gina web de la herramienta. segunda ) .5. la herramienta Ecl-Emma y su plugin para Eclipse son excelentes herramientas que contribuyen a aumentar la calidad de nuestro c´digo.1. En la primera parte n de este libro se expone con claridad los principios del Dise˜o de Software n Dirigido por Pruebas. 0 ) .eclemma. a Otra excelente referencia de autores espa˜oles es [6]. Un excelente libro. De lectura obligada si se quiere poner en pr´ctica las pruebas de software. si la l´ a ınea a sido cubierta completamente por la prueba.3. de modo autom´tia co. setEdad ( 5 0 ) . } Listado 6. 0 ) .10: Los tres m´todos cubren el 100 % del c´digo del m´todo que se e o e est´ probando. y lo que es de gran a ayuda. P e r s o n a segunda = new P e r s o n a ( ) . En la vista Coverage se muestra para cada clase probada. o Sin duda. Para instalar este plug-in basta seguir los mismo pasos que se mostraron en la Secci´n 4. segunda . En la segunda parte del libro se aplica lo expuesto en la primera parte al desarrollo de una aplicaci´n de ejemplo. donde se trata de un modo comn pleto las pruebas de software es la referencia [5]. pero este m´todo contiene un error ya que no se comprueba que a e las referencias sean distintas de null Existe modelos te´ricos que dan las pautas a seguir para garantizar que las o pruebas son exhaustivas. a s s e r t E q u a l s ( 0 .

104 CAP´ ITULO 6. Martin. En el cap´ ıtulo 9 de esta referencia [10] est´ dedicado a a las buenas pr´cticas en el dise˜o de test unitarios de prueba. PRUEBAS UNITARIAS CON JUNIT lenguajes de programaci´n que muestran los ejemplos con . a Otro excelente t´ ıtulo que deber´ figurar en todos las estanter´ de un ıa ıas buen desarrollador es Clean code de Robert C. o El cap´ ıtulo 10 de [13] presenta las c´mo realizar pruebas unitarias con o JUnit. y en el cap´ ıtulo 12 muestra como trabajar con Cobertura para analizar el grado de cobertura de nuestras pruebas.Net y Python. tambi´n conocido e como uncle Bob. o la aplicaci´n a Java con JUnit es directa. a n . Cobertura es otra excelente herramienta para el an´lisis de cobertura de las pruebas unitarias.

. . Serializaci´n . . . . . . . . . Flujos de caracteres . . . .5. . . para poder realizar entrada/salida en nuestras aplicaciones. 105 . . 7. .2. . . . . . . El sistema de ficheros . . .5. Flujos a ficheros .2. . . . . . . La potencia de la aproximaci´n de Java a las operaciones de entrada/salida o es que Java utiliza un concepto transversal con independencia del dispositivo sobre el que se trabaja. . . .2. . . . . . . .5. . . . . . .1. . . Flujos de caracteres a ficheros . . . .4. . . . . con una gran o cantidad de clases.6. Introducci´n o Ya conocemos como definir clases que contienen datos y m´todos que nos pere miten trabajar con las instancias de estas clases.2. . Flujos de bytes a ficheros . . . . . Decimos que los datos son de entrada cuando llegan a nuestra aplicaci´n desde una fuente de datos. . 7. . 7. una vez que hemos trabajado con nuestros datos nos interesa almacenarlos de manera permanente. . o ıa u El lenguaje de programaci´n Java nos proporciona un paquete.2.Cap´ ıtulo 7 Entrada y Salida Contenidos 7. . .5. Flujos de bytes . . . . . . . . . . En muchos casos. . . o . Conexi´n entre flujos de bytes y de caracteres o El sistema de ficheros y flujos a ficheros . de tal modo que sea posible recuperar nuestros datos m´s tarde para a seguir trabajando sobre ellos. . . 7. . 7. . que las operaciones de entrada/salida son susceptibles de lanzar gran a cantidad de excepciones que vamos a tener que gestionar tal y como vimos en el cap´ ıtulo 5. Ver´s. . 7. .1. . . . . . . . . 106 107 108 109 110 110 110 110 111 112 . 7. . . . . .3. . . . . Todo lenguaje de programaci´n proporciona una serie de mecanismos para o realizar operaciones de entrada y salida de datos. . . Independientemente de si la salida es hacia un fichero. . . . . . 7. .5. . . Flujos (Streams) . . .1. . . . . . . . . y que son o de salida cuando nuestra aplicaci´n env´ datos a alg´n sumidero de datos. . . . . . . . . . . . . . 7.

una conexi´n a una URL.1 se muestra gr´ficamente el concepto de a flujo. cuando queramos leer datos que nos llegan desde alguna fuente de datos. Flujos (Streams) Los flujos en Java son los canales por donde transita la informaci´n. Las operaciones de entrada/salida en Java siempre se realizan a trav´s de flujos que son independientes de las fuentes e o sumideros de datos. Por el contrario. el mecanismo de entrada/salida es el o mismo: el uso de Flujos (Streams). En Java existen dos grandes categor´ de flujos. Utilizaremos unos u otros para realizar operaciones de entrada/salida dependiendo de la naturaleza de los datos que recibamos desde una fuente de datos o enviemos a un sumidero de datos. cada una de ellas con sus ıas propias clases para realizar operaciones de entrada salida: los flujos de bytes y los flujos de caracteres. utilizaremos flujos de salida cuando nuestras aplicaciones quieran enviar datos a alg´n sumidero de datos. o un fichero en nuestro disco duro. lo que implica que vas a ver muchos nombres de clase nuevos. es decir.1. ENTRADA Y SALIDA Figura 7. En la Figura 7. de salida. pero presta atenci´n al nombre de las clases y ver´s o a que es muy significativo. o tener ambas direcciones. Por otro lado. u La potencia de los flujos est´ relacionada con su independencia de los dispoa sitivos de entrada/salida a los que se est´n conectando.1: El concepto de flujo representado gr´ficamente. Los flujos o pueden ser de entrada. veremos los detalles en la nominaci´n de las clases en o las siguientes secciones. no importa que el dispositivo de salida sea una consola en o pantalla. Desde el punto de vista e de nuestro c´digo. tambi´n ver´s que existe simetr´ entre e a ıa los nombres de las clases que realizan operaciones de lectura y las que realizan . Por otro lado. el mecanismo de salida siempre es el mismo. En las siguientes secciones se va a presentar una gran cantidad de nuevas clases. un Socket. no importa que el dispositivo de entrada sea el teclado. 7. a un Socket o una conexi´n de Internet. o un fichero en nuestro disco duro. Al principio puede parecer abrumador. el meo canismo de entrada siempre es el mismo.106 CAP´ ITULO 7. Utilizaremos flujos de entrada cuando a nuestras aplicaciones lleguen datos.

a Todas las clases que realizan operaciones de lectura de bytes extienden a la clase abstract InputStrem. ıa operaciones de escritura. por su lado. o dispositivos de salida como una consola en pantalla son ambos flujos de bytes. la clase contendr´ la palabra Output.2. F´ ıjate que ambas clases son abstract y por lo tanto no se pueden instanciar directamente.2. Si la operaci´n es de lectura. el nombre de la clase contendr´ la palabra Input. Esta doble simetr´ y el criterio ıa para nominar a las clases te resultar´ de gran ayuda para reconocer cual es el a cometido de una clase simplemente a trav´s de su nombre.2 se muestra algunas clases de la jerarqu´ de flujos de ıa bytes. tambi´n ver´s que existe simetr´ en el e a ıa nombre de las clases que correspondes a flujos de bytes y los nombres de las clases que corresponden a flujos de caracteres. es decir nos permiten la lectura/escritura de datos binarios. Flujos de bytes Los flujos de bytes nos permiten leer bytes desde una fuente de datos o escribir bytes hacia un sumidero de datos. dispositivos de entrada como el teclado. aunque lo que finalmente se lee o escriba a ellos sean caracteres. as´ por ejemplo. FLUJOS DE BYTES 107 Figura 7. todas las clases que realizan operaciones de escritura de bytes extienden a la clase abstract OutputStrem. y por ello. esta clase proporciona el m´todo float readFloat() ı e . Y finalmente. La clase DataInputStream permite abrir un fichero para leer tipos de datos primitivos. En la Figura 7.7. e 7. Las clases que nos permiten leer/escribir sobre flujos de bytes existen en Java desde las primeras versiones del lenguaje.2: Parte de la jerarqu´ de clases para flujos de bytes. si el o a flujo es de escritura. Existe simetr´ en el modo de nombrar a las clases que realizan operaciones ıa de lectura sobre flujos de bytes y las que realizan operaciones de escritura.

ıa que devuelve un n´mero real de precisi´n simple le´ desde un flujo. ıdo De modo an´logo. Estas clases son BufferedReader que nos proporciona un flujo de lectura de caracteres con buffer. la clase DataOutputStream permite abrir un flujo para esa cribir en ´l tipos de datos primitivos. ıa De nuevo.2.3 muestra una peque˜a parte de la jerarqu´ de clases existente n ıa en Java para los flujos de caracteres. 7. Flujos de caracteres La Figura 7. F´ ıjate en la analog´ con la Figura 7. abstract Reader en el caso de lectura de flujos de caracteres y abstract Writer en el caso de escritura. Las clases BufferedInputStream y BufferedOutputStream efect´an lectura u y escritura de bytes desde un flujo utilizando una memoria intermedia (buffer ) con el objeto de acelerar el proceso.3.108 CAP´ ITULO 7. disponemos e a de dos subclases que proporcionan una memoria intermedia para mejorar el rendimiento del proceso de lectura/escritura con flujos de caracteres. y boolean u o ıdo readBoolean() que devuelve un booleano le´ desde un flujo de bytes.3: Parte de la jerarqu´ de clases para flujos de caracteres. esta clase cuenta con el m´todo e String readLine() que nos permite leer cadenas de caracteres. . y en este caso contamos con m´todos como e e void writeFloat(float f) para escribir en un flujo de byte un n´mero real de u precisi´n sencilla y final void writeBoolean(boolean b) para escribir datos o booleanos sobre un flujo de bytes. En el caso de la clase BufferedReader. tenemos un par de clases abstractas. ENTRADA Y SALIDA Figura 7. y BufferedWriter que nos proporciona un flujo de escritura de caracteres con buffer. De nuevo. y tambi´n de modo an´logo a los flujos de bytes.

Listado 7. el primer tipo de flujos que se introdujo en Java desde la versi´n 1. Por otro lado. la clase Reader proporciona m´todos para leer caracter a caracter desde alguna fuente de datos. No es por lo tanto de extra˜ar que tanto el teclado. por ejemplo. CONEXION ENTRE FLUJOS DE BYTES Y DE CARACTERES 109 7. flujo de entrada de bytes. i n I n p u t S t r e a m R e a d e r i s r = new I n p u t S t r e a m R e a d e r ( i s ) . // El t e c l a d o e s Java e s System .´ 7. y sobre ´l que crea un flujo de escritura de caracteres. En la l´ ınea 2. como n la pantalla/consola sean flujos de bytes. n Tomando como ejemplo los flujos de entrada de caracteres. obtener de alg´n modo u flujos de tipo b´sico e ir construyendo sobre ellos nuevas instancias hasta llegar a a un flujo que nos proporcione la funcionalidad que necesitamos. flujo de salida de bytes. que es el flujo de entrada de byte desde el que queremos leer.1: T´cnica para leer caracteres desde teclado e En la l´ ınea 1 del Listado 7. e OutputStreamWriter toma una instancia de OutputStream. Conexi´n entre flujos de bytes y de caraco teres Como acabas de ver en las secciones anteriores. convertimos el flujo de entrada bytes a un flujo de entrada de caracteres con la ayuda de la clase InputStreamReader. y sobre ´l que crear un flujo de lectura de caracteres.1 aparecieron los o o flujos de caracteres.4. en este momento ya podr´ ıamos leer caracteres desde el teclado. // Lo decoramos con un f l u j o con memoria i n t e r m e d i a S t r i n g l i n e a = br . i n . Por otro lado los constructores de BufferedReader son: BufferedReader(Reader in) BufferedReader(Reader in.4.1 simplemente definimos la referencia is hacia el teclado. int sz) ambos necesitan una referencia a Reader para invocarse. y desde la versi´n 1. podamos leer cadenas de caracteres directamente desde el teclado? La respuesta a esta pregunta es que Java proporciona clases de conexi´n entre ambos tipos de flujos: o InputStreamReader toma una instancia de InputStream. La nueva instancia de BufferedReader se construye envolviendo a la instancia de Reader.1 muestra un ejemplo de uso de esta t´cnica para leer cadenas e de caracteres desde teclado: 1 2 3 4 I n p u t S t r e a m i s = System . Con todo esto. e y su clase hija BufferedReader a˜ade un buffer intermedio en la lectura de n modo que podemos leer l´ ıneas de caracteres (String) desde la fuente de datos. r e a d L i n e ( ) .0 fueron los flujos de bytes. la pregunta que nos surge es ¿C´mo se conectan los flujos de o caracteres con los flujos de bytes para que. // Ya podemos l e e r c a d e n a s de t e x t o d e s d e el teclado . // Lo decoramos como un f l u j o de c a r a c t e r e s B u f f e r e d R e a d e r br = new B u f f e r e d R e a d e r ( i s r ) . e El Listado 7. pero es m´s eficiente utilizar una memoria intermedia. a . hijas van a˜adiendo nueva funcionalidad sobre la que proporciona la clase padre. Y esta es la idea clave del trabajo con flujos en Java. para un determinado tipo de flujo existe varias clases definidas en el ´rbol de jerarqu´ de modo que las clases a ıa.

o 7.5.2. De nuevo. tal y e como se muestra en la l´ ınea 4 1 . 7. De modo an´logo. con independencia del sistema operativo sobre el que se ejecute. El sistema de ficheros y flujos a ficheros Un caso particular de fuente y sumidero de datos son los ficheros. ENTRADA Y SALIDA En la l´ ınea 3 estamos creando una instancia de la clase BufferedReader sobre el flujo de entrada de caracteres (InputStreamReader). podemos distinguir dos tipos de flujos a ficheros dependiendo de si la informaci´n contenida en ellos es de tipo binario o caracteres. y en general desde cualquier flujo de entrada. Como el acceso para realizar entrada/salida es independiente del dispositivo. podemos obtener informaci´n tal como la lista de ficheros o directorios bajo un directorio dado. sean estos datos de tipo binarios o caracteres.1. Esta clase nos da acceso al sistema de ficheros y sobre esta clase podemos construir flujos de entrada/salida par tipos de datos tanto binarios como caracteres. Podemos e instanciar esta clase tambi´n a partir de una referencia a File o bien a partir e de un String que represente el camino hasta el fichero. o o comprobar si el camino con el que se construye la instancia de File hace referencia a un fichero o a un directorio.5. Flujos a ficheros Los flujos a ficheros nos permiten acceder a la informaci´n contenida en los ficheo ros de nuestro sistema con el fin de leer desde ellos o escribir informaci´n hacia o ellos.1. Para ello Java nos proporciona la clase File. No obstante lo que aqu´ se ha mostrado es un ejemplo del mecanismo general de conversi´n entre flujos de ı o caracteres y flujos de bytes . En el momento de la creaci´n del flujo podemos indicar si queremos conservar el posible contenido o del fichero en el momento de la creaci´n del flujo a trav´s de un argumento de o e tipo booleano en el constructor. 1 En el Cap´ ıtulo 8 se mostrar´ un clase de utilidad Scanner que facilita enormemente la a lectura de datos desde teclado. Gracias a esta clase. 7. la clase FileOutputStream nos permite crear un flujo de a escritura hacia un fichero para escribir en ´l datos de tipo binario. sea estos datos de tipo binarios o caracteres. El sistema de ficheros La clase File nos da acceso al sistema de ficheros. y podemos escribir datos a un fichero.2. Flujos de bytes a ficheros La clase FileInputStream nos permite crear un flujo de lectura hacia un fichero para leer desde ´l datos de tipo binario. Podemos instanciar esta clase a partir e de una referencia a File o bien a partir de un String que represente el camino hasta el fichero. para poder finalmente leer cadenas de caracteres con la ayuda del m´todo String readLine().110 CAP´ ITULO 7. lo que necesitaremos en este caso es alg´n medio para acceder al sistema de u ficheros.5. 7.5. Desde nuestros programas podemos leer los datos contenidos en un fichero.

. y su o ejecuci´n es la siguiente: si se produce alguna excepci´n durante el trabajo con o o el fichero (l´ ıneas de c´digo 18-23)... ..2.2. File . FileReader flujoLectura . El uso de estos bucles anidados facilita la lectura de c´digo. FileNotFoundException . while ( ( l i n e a = f l u j o B u f f e r .. EL SISTEMA DE FICHEROS Y FLUJOS A FICHEROS 7. . ..} en las l´ ıneas 17-27 que est´ incluido dentro de otro bloque a try{. } } public s t a t i c void main ( S t r i n g [ ] a r g s ) { new L e c t u r a F l u j o T e x t o ( ) . io io io io io .. el Listado 7. public c l a s s L e c t u r a F l u j o T e x t o { public L e c t u r a F l u j o T e x t o ( ) { super ( ) . f l u j o B u f f e r = new B u f f e r e d R e a d e r ( f l u j o L e c t u r a ) . printStackTrace () .2: Lectura desde un flujo de texto hacia un fichero Como curiosidad del Listado 7.. podemos instanciar esta clase a partir de a una referencia File. de un String que indique el camino al fichero. p r i n t l n ( l i n e a ) . IOException . FileReader . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import import import import import java java java java java .} con lo o a que se cerrar´ el fichero. que es quien tiene los bloques catch{. r e a d L i n e ( ) ) != n u l l ) { System .2 muestra c´mo abrir un o flujo a un fichero de caracteres para leer desde ´l l´ e ınea a l´ ınea su contenido y mostrarlo por consola. ..} para atrapar a cada una de . } catch ( I O E x c e p t i o n e ) { e .2.5. o Como ejemplo del manejo de ficheros. . } } catch ( F i l e N o t F o u n d E x c e p t i o n e ) { e . } private void e j e c u t a ( S t r i n g camino ) { F i l e f i c h e r o = new F i l e ( camino ) . la clase FileWriter nos permite crear un flujo de escritura de caracteres hacia un fichero para escribir en ´l datos de tipo caracter. } } Listado 7. podemos instanciar esta clase s partir de una referencia a File o bien a partir de un String que represente el camino hasta el fichero. De modo an´logo al caso de e a FileInputStream. printStackTrace () . . Flujos de caracteres a ficheros 111 La clase FileReader nos permite crear un flujo de lectura hacia un fichero. e j e c u t a ( a r g s [ 0 ] ) . } } finally { i f ( f l u j o B u f f e r != n u l l ) flujoBuffer . BufferedReader . e indicar en el momento de la creaci´n si el fichero conserva o no el posible contenido. . Finalmente. para leer desde ´l datos de tipo caracter.. close () .} exa o a terno. BufferedReader f l u j o B u f f e r = null . String linea .} finally{.}. . o u t .7. De modo e an´logo a la clase FileOutputStream. se ejecutar´ el bloque finally{. f´ ıjate que hay un bloque try{.. y la excepci´n se propagar´ al bloque try{.5.. try { try { f l u j o L e c t u r a = new F i l e R e a d e r ( f i c h e r o ) .

112 CAP´ ITULO 7. pero eso no garantiza que otro programador pueda utilizar el mismo n´mero de u serie para una clase completamente distinta.6. serializacion. esta herramienta es serialver. como la clase de la instancia y un n´mero de a o u serie de la clase. es unicamente una u e ´ marca sem´ntica para que Java sepa que en alg´n momento podemos querer a u serializar el objeto. podemos enviar el objeto a cualquier dispositivo que lo acepte.Persona serializacion. Este modo de codificaci´n es ampliamente utilizado y o conviene que lo incorpores como t´cnica de escritura de tu propio c´digo. Son a aplicaciones que se no se ejecutan en las m´quinas de un cliente. El valor de este atributo lo podemos fijar nosotros mismos. Por convenci´n. Y es muy improbable que serialver genere el mismo n´mero de versi´n para cualquier otra clase. e o 7. a Usualmente. Serializaci´n o La Serializaci´n es el mecanismo por el cual Java es capaz de convertir un objeto o en una secuencia de bytes. esta t´cnica es tan potente que es la e pieza sobre la que descansan otras tecnolog´ Java como la invocaci´n remota ıas o de m´todo (Remote Method Innvocation . o e Para indicar que un objeto es Serializable debe implementar la interface Serializable. 2 Java 2 Enterprise Edition est´ enfocada al desarrollo de aplicaciones de servidor. o En esta secci´n vamos a presentar la serializaci´n y c´mo utilizarla para o o o almacenar un objeto en un fichero. a podr´ ıamos conectarnos a una fuente de datos a trav´s de un flujo de entrada e y obtener objetos desde ella. este n´mero de control se declara como private static final long o u serialVersionUID. ENTRADA Y SALIDA las excepciones posibles.RMI ). lo u o que nos garantiza que este n´mero de versi´n es unico e identifica a la clase u o ´ Persona. podemos crear un flujo a partir de la secuencia de bytes que representa al objeto para escribirlo en un fichero o enviarlo a trav´s de un Socket por ejemplo. si no en un servidor remoto. Y de modo an´logo.Persona: static final long serialVersionUID = 7360368493593648647L. para poder hacer un control de versiones de la clase. Cuando el objeto serializable se convierta en una secuencia de bytes. Esta interface no declara ning´n m´todo. adem´s de incluir el valor de los atributos de la insa tancia incluye m´s informaci´n. esta secuencia. y en el Cap´ ıtulo 15 veremos c´mo utilizar la o serializaci´n para enviar y recibir objetos a trav´s de un Socket. y gran parte de las tecnolog´ e ıas Java en su edici´n Enterprise 2 . aunque no es la unica e ´ opci´n posible o . que genera n´meros de versi´n a partir de la clase u o compilada. De este modo. Java nos proporciona una herramienta. En este caso la herramientaserialver ha generado el n´mero de serie u 7360368493593648647L para la clase Persona. De hecho. el ciente accede al servidor a trav´s de un navegador web. si somos capaces o de obtener una secuencia de bytes del objeto y sobre ella crear un flujo. su uso es serialver [-classpath] nombreClase y un ejemplo de uso es: $ serialver -classpath . e El concepto de serializaci´n es extremadamente potente. integrada en el JDK.

. nombre = nombre . S t r i n g nombre . } private void e j e c u t a ( S t r i n g fichero ) { . n a u El Listado 7. public c l a s s P e r s o n a implements S e r i a l i z a b l e { private s t a t i c f i n a l long s e r i a l V e r s i o n U I D = 7 3 6 0 3 6 8 4 9 3 5 9 3 6 4 8 6 4 7L . IOException .´ 7. } S t r i n g getNombre ( ) { return nombre . import import import import import import java java java java java java . S e r i a l i z a b l e . ObjectOutput . a p e l l i d o s = a p e l l i d o s . this . SERIALIZACION 113 Eclipse es capaz de invocar a serialver de manera transparente. public c l a s s E s c r i t o r P e r s o n a { public E s c r i t o r P e r s o n a ( ) { super ( ) . . } } String telefono ) { Listado 7. S t r i n g a p e l l i d o s . ObjectOutputStream . . Persona ( ) { } P e r s o n a ( S t r i n g nombre . } String getTelefono () { return t e l e f o n o . t h i s . } String getApellidos () { return a p e l l i d o s . telefono =" + telefono + "]" . o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package s e r i a l i z a c i o n . this .6. . FileNotFoundException . . . . y c´mo almacenar la secuencia de bytes obtenida en un fichero para o su recuperaci´n posterior. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package s e r i a l i z a c i o n .3 muestra la clase Persona que implementa la interface Serializable y a la que se le ha a˜adido el n´mero de versi´n generado con n u o serialver. } @Override public S t r i n g t o S t r i n g ( ) { return " P e r s o n a [ a p e l l i d o s = " + a p e l l i d o s + " . Eclipse nos mostrar´ un aviso. . String apellidos . t e l e f o n o = t e l e f o n o . n o m b r e = " + nombre + " . String telefono .3: La clase Persona lista para ser serializada El Listado 7. o se a˜adir´ el n´mero de serie obtenido con serialver. io io io io io io . . FileOutputStream .4 muestra un ejemplo de como serializar esta clase y la secuencia de bytes. . import j a v a . Si nuestra nueva clase implementa la interface Serializable y olvidamos incluir el atributo serialVersionUID. Si corregimos el aviso a que nos da Eclipse seleccionando la opci´n Add generated serial verion ID. i o . OutputStream .

} } catch ( F i l e N o t F o u n d E x c e p t i o n e ) { e . ObjectInput . try { try { s t r e a m L e c t u r a = new F i l e I n p u t S t r e a m ( f i c h e r o ) . e j e c u t a ( a r g s [ 0 ] ) . ObjectOutput s t r e a m E s c r i t u r a P e r s o n a = n u l l . printStackTrace () . introduciendo por l´ ınea de instrucciones como nombre de fichero persona. . } finally { i f ( s t r e a m E s c r i t u r a P e r s o n a != n u l l ) s t r e a m E s c r i t u r a P e r s o n a . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package s e r i a l i z a c i o n . IOException . w r i t e O b j e c t (new P e r s o n a ( " J a m e s " . } } Listado 7. para los ficheros que contienen datos de objetos serializados se utiliza la o extensi´n . } } catch ( F i l e N o t F o u n d E x c e p t i o n e ) { e . printStackTrace () . s t r e a m E s c r i t u r a P e r s o n a = new ObjectOutputStream ( s t r e a m E s c r i t u r a ) . } catch ( C l a s s N o t F o u n d E x c e p t i o n e ) { e . El Listado 7. . printStackTrace () . " 555 123 456 " ) ) . ObjectInputStream . . try { try { s t r e a m E s c r i t u r a = new F i l e O u t p u t S t r e a m ( f i c h e r o ) . c l o s e ( ) . FileNotFoundException . " G o s l i n g " . p r i n t l n ( p e r s o n a ) . printStackTrace () . } finally { i f ( s t r e a m L e c t u r a P e r s o n a != n u l l ) s t r e a m L e c t u r a P e r s o n a .ser 3 se crear´ un fichero de tipo a binario cuyo contenido es una instancia de la clase Persona cuyos atributos tienen los valores asignados. } 3 Por convenci´n. readObject ( ) . . } private void e j e c u t a ( S t r i n g f i c h e r o ) { InputStream streamLectura . .5 muestra un ejemplo completo de c´mo leer un objeto serialio zado almacenado en un fichero de tipo binario. . } catch ( I O E x c e p t i o n e ) { e . printStackTrace () . System .ser o .114 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 CAP´ ITULO 7. . . s t r e a m L e c t u r a P e r s o n a = new O b j e c t I n p u t S t r e a m ( s t r e a m L e c t u r a ) . o u t . } } public s t a t i c void main ( S t r i n g [ ] a r g s ) { new E s c r i t o r P e r s o n a ( ) . FileInputStream . InputStream .4: Serializaci´n de la clase Persona hacia un fichero de bytes o Si ejecutamos el programa Java anterior. public c l a s s L e c t o r P e r s o n a { public L e c t o r P e r s o n a ( ) { super ( ) . } catch ( I O E x c e p t i o n e ) { e . io io io io io io . import import import import import import java java java java java java . . . Persona persona = ( Persona ) streamLecturaPersona . c l o s e ( ) . ENTRADA Y SALIDA OutputStream s t r e a m E s c r i t u r a . ObjectInput streamLecturaPersona = null . s t r e a m E s c r i t u r a P e r s o n a .

para que sea poo sible almacenar los datos de los contactos en un fichero de texto para su posterior recuperaci´n. o .6. de nuevo. En particular las secciones dedicadas a la serializaci´n de objetos son muy interesantes. 2. a trav´s de una red de comunicaci´n de datos. con lo que podremos escribir un servidor capaz de enviarnos. Escribe tanto el c´digo de escritura como el de lectura.} anidados para o facilitar la gesti´n de excepciones. Sigue ampliando la funcionalidad de tu aplicaci´n de la agenda para que o sea posible serializarla a un fichero de tipo binario para su posterior recuperaci´n. Escribe tanto el c´digo de escritura como de o o lectura. Amplia la funcionalidad de la aplicaci´n de la agenda. SERIALIZACION 34 35 36 37 38 39 40 115 } public s t a t i c void main ( S t r i n g [ ] a r g s ) { new L e c t o r P e r s o n a ( ) . Ejercicios 1. La referencia [3] dedica tambi´n todo el Cap´ e ıtulo 14 al estudio del mecanismo de entrada/salida en Java.. objetos e o serializados y podremos recuperarlos en un cliente. o En el cap´ ıtulo 15 se mostrar´ otro ejemplo de serializaci´n de objetos pero a o esta vez se enviar´ la secuencia de bytes que representa al objeto a trav´s de a e los flujos que proporciona un Socket. } } Listado 7.5: Des-serializaci´n de la clase Persona desde un fichero de bytes o F´ ıjate c´mo.. se han utilizado bloques try{. e j e c u t a ( a r g s [ 0 ] ) . o o Lecturas recomendadas La referencia [2] dedica todo el Cap´ ıtulo 15 al estudio del mecanismo de entrada/salida en Java.´ 7.

ENTRADA Y SALIDA .116 CAP´ ITULO 7.

. . . n aunque existen otras muchas tan utiles como las aqu´ presentadas. . . . . . . . . . 117 . .3. . . . . . . . . . . . . . . . . . .2. .2. . . Colecciones . . . . 8.1. 8. . . . . . . . . . . . . . . Trabajo con fechas . . . . . . . La clase Random . . . .2. . . . . En este Cap´ ıtulo presentamos un peque˜o grupo de clases de gran utilidad. . . . . . . . . 8. Las clases Calendar y GregorianCalendar . . a 8. . 8.5. . . . . . . . . . . . . . . . . . . . . . . .5. 8. Las clases StringBuffer y StringBuilder . La clase Scanner . . . .2. . . 8. . . . . . 118 120 120 121 122 124 128 128 129 129 129 130 . .2. . . La clase Math . . . . .6. . Matem´ticas . . 8.5. por cuesti´n de espacio. Obviamen´ ı te. . . . . . . . . . . . . . . .1. . . . . . . . . . . . . . . . .6. . . Introducci´n o La edici´n est´ndar de Java proporciona una ampl´ o a ısima colecci´n de clases ya o definidas. . . . La clase Date . . . .2. . . . . .6. . . .Cap´ ıtulo 8 Algunas clases de utilidad del paquete est´ndar a Contenidos 8. . . . 8. Trabajo con cadenas de caracteres .1. . 8. . . 8. . . . . . . . . . Estas clases ya definidas son de gran utilidad. . a medida que como programadores vamos conociendo nuevas clases de esta colecci´n nuestra proo ductividad aumenta. s´lo presentamos las que creemos m´s interesantes o o a llegados a este punto. . . . . . Clases recubridoras . . .1. . . . . . .4. . . . . La clase String .

es 1 Para . i o . } catch ( F i l e N o t F o u n d E x c e p t i o n e ) { e . private U t i l i d a d S c a n n e r ( ) { super ( ) . i o . hasNext ( ) ) System .1 muestra un ejemplo de uso de la clase Scanner para leer l´ ınea a l´ ınea de este fichero. La clase Scanner est´ presente en Java desde la versi´n 5. El uso de la clase de utilidad Scanner nos oculta los flujos y nos permite leer directamente de flujos. while ( s c a n n e r .wikipedia. tenemos que aplicar la t´cnica del recubrimiento que vimos en el Cap´ e ıtulo 7 para conseguir leer cadenas de caracteres. El m´todo hasNext() nos sirve para comprobar si hay e m´s elementos a devolver. public f i n a l c l a s s U t i l i d a d S c a n n e r { private s t a t i c f i n a l S t r i n g FICHERO = " a g e n d a .1.org/wiki/Regular_expression 2 Estos datos se han generado aleatoriamente tomando como base los datos estad´ ısticos del Instituto Nacional de Estad´ ıstica. n e x t L i n e ( ) ) . Como finalmente lo que nos interesa leer desde el teclado son caracteres. import j a v a . import j a v a . Para guardar la compatibilidad hacia atr´s. e Supongamos que tenemos un fichero de texto que almacena datos de una agenda de tel´fonos con el formato Persona: Nombre: Apellidos: Telefono. t x t " . Estos datos estad´ ısticos se pueden consultar en la direcci´n o http://www. F i l e N o t F o u n d E x c e p t i o n . S c a n n e r .´ 118CAP´ ITULO 8. e un ejemplo de contenido del fichero es2 : Persona: Persona: Persona: Persona: Persona: LUISA: GARCIA MORENO: 313372295 ROSARIO: GONZALEZ ESTEBAN: 560248322 MANUEL: SANZ GARCIA: 571365702 FRANCISCO: VAZQUEZ FERRER: 690109651 VICTOR: MU~OZ LOPEZ: 500661266 N El Listado 8. printStackTrace () . Esta clase pera o mite analizar una cadena de texto utilizando para ello expresiones regulares 1 . en particular desde el teclado.0 de Java no exist´ flujos de o ıan caracteres. import j a v a . tanto el teclado como la a consola siguen siendo flujos de caracteres en las versiones actuales de Java. a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package u t i l i d a d .ine. } } public s t a t i c void main ( S t r i n g [ ] a r g s ) { new U t i l i d a d S c a n n e r ( ) . o u t . e j e c u t a ( ) . ALGUNAS CLASES DE UTILIDAD DEL PAQUETE ESTANDAR 8. Esto se debe a que en la versi´n 1. Las cadenas se pueden proporcionar directamente en el momento de crear la instancia de clase Scanner o a trav´s de un flujo. F i l e . p r i n t l n ( s c a n n e r . u t i l . La clase Scanner En el Cap´ ıtulo 7 comentamos que en Java tanto la consola como el teclado son flujos de bytes. } m´s informaci´n sobre qu´ son expresiones regulares el lector puede consultar http: a o e //en. } private void e j e c u t a ( ) { try { S c a n n e r s c a n n e r = new S c a n n e r (new F i l e (FICHERO) ) .

PEREZ HERRERA.2. nextLine () ) . } } catch ( F i l e N o t F o u n d E x c e p t i o n e ) { e . F i l e . S t r i n g p e r s o n a .VARGAS MARTINEZ. " + a p e l l i d o s + " . useDelimiter ( ": " ) . nombre = s c a n n e r . t x t " . private U t i l i d a d S c a n n e r 2 ( ) { super ( ) . scanner . } private void e j e c u t a ( ) { try { S c a n n e r s c a n n e r = new S c a n n e r (new F i l e (FICHERO) ) . int t e l e f o n o .520908284 JULIA. } public s t a t i c void main ( S t r i n g a r g s [ ] ) { new U t i l i d a d S c a n n e r 2 ( ) . } } Listado 8. hasNext ( ) ) { analizaLinea ( scanner . while ( s c a n n e r . import j a v a . next ( ) . persona = scanner .ALVAREZ MARTIN.945953372 MANUEL. i o .482596843 TOMAS.1: Lectura de l´ ıneas de texto desde un fichero con el uso de la clase Scanner La clase Scanner tiene m´todos para poder leer tipos de datos primitivos e tal y como se muestra en el Listado 8. i o . n e x t ( ) . a p e l l i d o s = scanner .3. LA CLASE SCANNER 26 27 119 } Listado 8.CASTRO RUIZ.ALVAREZ ORTEGA. con la clase Scanner podremos leer tipos de datos primitivos.8. tal y como muestra el Listado 8. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package u t i l i d a d . . } } private void a n a l i z a L i n e a ( S t r i n g l i n e a ) { S c a n n e r s c a n n e r = new S c a n n e r ( l i n e a ) . t e l e f o n o = scanner . S c a n n e r . import j a v a . printStackTrace () . nombre .2: Lectura de l´ ıneas de texto desde un fichero con el uso de la clase Scanner El resultado de la ejecuci´n de este c´digo es el siguiente: o o FRANCISCO JOSE. import j a v a . u t i l . next ( ) .691825532 Si construimos la instancia de Scanner sobre el flujo de bytes que representa al teclado System. nextInt () . o u t .90727037 ROBERTO. F i l e N o t F o u n d E x c e p t i o n .in. System . " + t e l e f o n o ) . public f i n a l c l a s s U t i l i d a d S c a n n e r 2 { private s t a t i c f i n a l S t r i n g FICHERO = " a g e n d a . p r i n t l n ( nombre + " . e j e c u t a ( ) .1. a p e l l i d o s .

ı 1 2 3 S t r i n g primera = " Hola " . con el coste que supone la creaci´n de objetos. o u t . Por la tanto es util ´ utilizar esta clase cuando no vamos a hacer manipulaciones continuadas sobre la cadena que representa. caracter a caracter. p r i n t l n ( " I n t r o d u c e u n r e a l : " ) . No obstante.4 se crean tres objetos de tipo String. Al concatenar dos cadenas se crea una nueva cadena para almacenar el resultado. 1 S t r i n g cadenaConcatenada = " H o l a " + " . de ah´ la ineficiencia al utilizar el operador + sobre String.2. no se amplia ninguna de las cadenas originales para albergar la nueva cadena. c o m o e s t a s " . una vez creada no se puede modificar la secuencia de caracteres. el segundo contiene . a 8. " S t r i n g r e s u l t a d o = p r i m e r a + segunda . o u t . La clase String La clase String representa una cadena de caracteres inmutable. p r i n t ( " I n t r o d u c e u n e n t e r o : " ) . o u t . System . A efectos pr´cticos la inmutabilidad de la clase o a String significa que cuando concatenamos dos cadenas el resultado es una nueva cadena. la clase String. nextInt ( ) .2. el primero de ellos contiene la cadena de caracteres Hola.4: ”La concatenaci´n de dos cadenas crea una nueva cadena. 8. como est´s. Para comparar dos cadenas de caracteres.1. System . ALGUNAS CLASES DE UTILIDAD DEL PAQUETE ESTANDAR 1 2 3 4 5 6 S c a n n e r l e c t o r T e c l a d o = new S c a n n e r ( System . El unico operador sobrecargado en Java es el operador + cuando se aplica ´ sobre cadenas con el significado de concatenarlas. int entero = l e c t o r T e c l a d o . La clase Scanner nos permite leer desde cualquier flujo de entrada. tal y como muestra el Listado 8.5. Java proporciona clases m´s eficientes para trabajar con a cadenas. System . Listado 8. i n ) . no debemos cometer el error de utilizar el operador == ya que este operador compara la igualdad de dos referencias. nextFloat () . no s´lo o desde el teclado. se crean nuevas instancias de esta clase. r e a l = " + r e a l ) .5: Uso del operador + para concatenar dos cadenas de caracteres. es decir. ´ Listado 8. Listado 8.3: La clase Scanner nos permite leer tipos primitivos desde teclado.´ 120CAP´ ITULO 8. como est´s y el a tercero contiene Hola. p r i n t l n ( " E n e r o = " + e n t e r o + " . ya que la clase String es inmutable y al manipular las cadenas de texto que representa. Para comparar dos cadena de caracteres utilizamos el m´todo public boolean equals(Object o). S t r i n g segunda = " m u n d o . Trabajo con cadenas de caracteres Ya conoces una clase que representa y manipula cadenas de caracteres. float r e a l = lectorTeclado .” o En el Listado 8. El o . que compara el String actual e con la representaci´n como String del objeto que se le pasa como argumento.

2. El Listado 8.2. si queree u u mos comparar dos cadenas con independencia del uso de may´sculas/min´sculas u u utilizaremos el m´todo public boolean equalsIgnoreCase(String s). Listado 8. El Listado 8. f´ e ıjate que estamos dividiendo la cadena original buscando el patr´n representado por otra cadena. p r i n t l n ( t r o z o ) . ". por ejemplo.7: Ejemplo de formato usando el m´todo format de la clase String e El resultado de la ejecuci´n del Listado 8. queremos concatenar dos cadenas. y el m´todo u e e public String toUpperCase en caso de que la queramos en may´sculas. 3 . la clase String nos proporciona el m´todo public static String format(String cadena. por la que quiero t r o c e a r .. si no que se modifica la original para representar la cadena concatenada final. s p l i t (". Si queremos convertir todas las letras de una cadena a min´sculas utilizamos el m´todo public String toLowerCase(). e argumentos. 1 System . o Un m´todo interesante que nos permite trocear una cadena de caracteres a e partir de una subcadena contenida en ellas es String split(String s). Esta clase es la recomendada si.14 Si se necesitan formatos m´s sofisticados. e El resultado de la ejecuci´n de este c´digo es: o o Esta cadena contiene comas por la que quiero trocear. ya que el resultado no crea una nueva cadena.7 muestra un sencillo caso de uso. for ( String trozo : t r o z o s ) System .8. Las clases StringBuffer y StringBuilder La clase StringBuffer tambi´n representa una cadena de caracteres coe mo la clase String pero esta vez la cadena que representa puede cambiar.6 muestra un ejemplo de uso o del m´todo split. o u t ." .. donde el argumento es una expresi´n regular. o 1 2 3 4 S t r i n g i n i c i a l = " Esta cadena . la clase Formatter es de gran a ayuda. p r i n t l n ( S t r i n g . String trozos [ ] = i n i c i a l . e Para averiguar el n´mero de caracteres de una cadena utilizamos el m´todo u e public int length(). Para poder dar formato a cadenas al estilo de C. o u t .2. 1 4 1 5 ) ) . TRABAJO CON CADENAS DE CARACTERES 121 m´todo equals(Object o) distingue entre may´sculas y min´sculas. 8. c o n t i e n e comas . Object. u La clase String tambi´n posee el m´todo sobrecargado static String e e valueOf(boolean/char/int/long/float/double) para convertir tipos de datos primitivos a su representaci´n como cadenas de caracteres. ".7: o El valor de PI es: 3. Para ello la clase StringBuffer posee el m´todo sobrecargado StringBuffer e . f o r m a t ( " E l v a l o r d e P I e s : \ % 2 . 2 f " . Listado 8.6: Uso del m´todo split para trocear una cadena. ") .

b o o l e a n o V e r d a d e r o = new B o o l e a n ( true ) . los tipos de datos primitivos y los tipos de datos referencia.9. pero esta vez ninguno de ellos est´ sincronizado por razones de eficiencia3 . como con cualquier otro objeto.´ 122CAP´ ITULO 8. luego se pueden utilizar en aplicacioa nes en las que varios hilos est´n accediendo a la misma referencia de la clase a StringBuffer. el m´todo int indexOf(String s) devuelve la poo e sici´n de la primera ocurrencia de la cadena s dentro de la cadeo na original. El m´todo sobrecargado StringBuffer insert(int offset. en Java existen dos grandes grupos de tipos de datos.4. i n s e r t ( sb .3. como tipos primitivos. el acceso a m´todos sincronizados tiene un sobrecoste e temporal debido al uso de cerrojos. a 8.8 muestra un ejemplo de uso de estos m´todos. Tal y como muestra la Tabla 8. es decir. e n t e r o S t r i n g = new I n t e g e r ( " 1 0 " ) .8: Uso de los m´todos indexOf y insert de la clase StringBuffer e Los m´todos que manipulan la representaci´n de la cadena dentro de la e o clase StringBuffer est´n sincronizados. " ) . Esto es e especialmente util al trabajar con colecciones. " ) . Por ejemplo. Por su parte. i n d e x O f ( " . Sin embargo. El Listado 8. o u t . sb . la clase StringBuilder funciona exactamente igual que la clase StringBuffer. System . e boolean/char/int/long/float/double/String) inserta la representaci´n del o segundo argumento en la cadena original a partir del offset indicado en el primer argumento. donde se crean clases recubridoras tanto a partir de datos primitivos como a partir de la representaci´n como o cadena de texto de los datos primitivos. o Para recuperar. Crear una clase recubridora a partir de un tipo primitivo es muy sencillo. Listado 8. Listado 8. e 1 2 3 S t r i n g B u f f e r sb = new S t r i n g B u f f e r ( " H o l a . tal y como veremos en la Secci´n ´ o 8. tal y como muestra el Listado 8. para cada tipo primitivo existe una clase recubridora. de hecho los m´todos que proporciona la clase StringBuilder e son exactamente los mismo que la clase StringBuffer. Java proporciona clases que recubren los tipos de datos primitivos para poder trabajar con ellos a trav´s de referencias. p r i n t l n ( sb ) .1. ALGUNAS CLASES DE UTILIDAD DEL PAQUETE ESTANDAR append(boolean/int/long/float/double/String/StringBuffer) que a˜ade n la representaci´n como String del argumento a la cadena actual. o La clase StringBuffer posee otros m´todos interesantes de manipue laci´n.10 e 3 Como veremos en el Cap´ ıtulo 14. . " J a v a " ) . 1 2 3 4 Integer Integer Boolean Boolean e n t e r o = new I n t e g e r ( 1 5 ) . b o o l e a n o F a l s o = new B o o l e a n ( " f a l s e " ) . los valores que almacena una clase recubridora. estas proporcionan m´todos tal y como muestra el Listado 8. Veremos el uso de hilos y lo que significa que un m´todo est´ sine e cronizado en el Cap´ ıtulo 14.9: Ejemplo de creaci´n de clases recubridoras. Clases recubridoras Como ya sabes.

de modo an´logo cada clase recubridora. 1 2 int ente roPrimit ivo = entero .11: Ejemplos de autoboxing para la conversi´n entre tipos de datos o primitivos y sus correspondientes clases recubridoras. o . boolean b o o l e a n o P r i m i t i v o = b o o l e a n o V e r d a d e r o . Listado 8.4. double r e a l = Double . Listado 8. El mecanismo de Autoboxing es especialmente util cuando se utilizan las ´ clases colecci´n.Byte java. Sin embargo. en la columna de la derecha.lang. Un grupo de m´todos especialmente util cuando se procesan datos de ene ´ trada de tipo texto.Boolean java. tal y como veremos en la Secci´n 8.8. tiene un m´todo para a e realizar la correspondiente conversi´n. o o 1 2 int e n t e r o = I n t e g e r .12.12: M´todos para obtener tipos primitivos a partir de cadenas de e caracteres.Character java.11. b o o l e a n V a l u e ( ) .3.lang.lang.Void java. B o o l e a n b o o l e a n o V e r d a d e r o = true . de modo autom´tico y transparente para el usuario.Float java. boolean b o o l e a n o P r i m i t i v o = b o o l e a n o V e r d a d e r o . p a r s e I n t ( " 10 " ) .Double 123 Tabla 8. 1 4 1 5 9 2 " ) .lang.lang.1: Para cada uno de los tipos primitivos de la columna de la izquierda. p a r s e D o u b l e ( " 3 .Long java. y los queremos convertir a tipos primitivos son los que muestra el o Listado 8. tal y como muestra el Listado 8.10: Recuperaci´n de los datos como tipos primitivos a partir de las o clases recubridoras. como por ejemplo los par´metros de llamada a nuestra a aplicaci´n.lang.lang.Short java. intValue ( ) . 1 2 3 4 Integer entero = 15.lang. Este mecanismo o convierte. tipos primitia vos a recubridores en una asignaci´n siempre que el tipo primitivo y la clase o recubridora sean compatibles.lang. en la mayor´ de los casos es de gran utilidad hacer uso del ıa mecanismo de Autoboxing introducido en la versi´n 5 de Java. int ente roPrimit ivo = entero .Integer java. Java proporciona una clase recubridora. Listado 8. CLASES RECUBRIDORAS Tipo primitivo void boolean char byte short int long float double Clase recubridora java.

En . tablas de dispersi´n. o 8.4. etc´tera. los s´ ımbolos < E > a continuaci´n de las interfaces o las clases. conjuntos.1: Interfaces b´sicos presentes en el Java Collections Framework. Vector< E > LinkendList< E > HasMap< E >.4 muestra los interfaces b´sicos definidos en el Java Collections a Framework.´ 124CAP´ ITULO 8. LinkendList< E >. Las clases que representan colecciones de referencias pueden implementar uno o m´s de estos interfaces. Colecciones Las clases que forman parte del grupo de clases colecci´n son aquellas que nos o sirven para almacenar referencias a objetos. Veremos con detalle c´mo utilizar gen´ricos en nuestra propias clases en el Cap´ o e ıtulo 9.2 hay una novedad. La Figura 8. El conjunto de intero e faces. mientras que en la parte derecha de la figura se muestran los interfaces que representan la funcionalidad de las clases que implementen colecciones donde cada elemento de la colecci´n representa una pareja o clave/valor.2 muestra algunas clases colecci´n y a o los interfaces que implementan. La parte de la derecha de esta figura muestra los interfaces que representan la funcionalidad de las clase que implementan colecciones de referencias como ((conjuntos)). F´ ıjate que en la Tabla 8.2: Varias clases colecci´n y los interfaces que implementan. ALGUNAS CLASES DE UTILIDAD DEL PAQUETE ESTANDAR Figura 8. esta sintaxis significa que la interface o la clase o almacena un tipo Gen´rico. La Tabla 8. e implementan estructuras de datos tales como listas. HashTable< E > TreeMap< E > Tabla 8. a Interface Set< E > SortedSet< E > List< E > Queue< E > Map< E > SortedMap< E > Implementaci´n o HashSet< E > TreeSet< E > ArrayList< E >. En el momento de creaci´n de la clase debemos ese o pecificar cual es el tipo de los elementos que va a contener la clase. clases y algoritmos que nos permiten trabajar con estructuras de datos se agrupan bajo el Java Collections Framework.

f i g u r a s . } @Override public S t r i n g t o S t r i n g ( ) { S t r i n g B u i l d e r b u i l d e r = new S t r i n g B u i l d e r ( ) .17 muestra un ejemplo de c´mo utilizar la clase a o ArrayList< F igura > para contener referencias a clases que implementen la interface Figura. a ella podemos a˜adir c´ n ırculos. b u i l d e r . append ( " A r e a = " ) . return b u i l d e r . f i g u r a s .13: Interface que declara la funcionalidad del c´lculo del ´rea de una a a figura geom´trica. Finalmente. b u i l d e r . radio = radio . References to a generic type ArrayList< E > should be parameterized no un error. En este caso. An´logamente. e 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package c o l e c c i o n e s . y los a podemos recuperar utilizando un bucle for. } . Aunque.15 define la clase Rectangulo a a de cuyas instancias tambi´n podemos calcular el ´rea. es posible instanciar las clases colecci´n sin eso o pecificar el tipo de los elementos que contendr´.4. public i n t e r f a c e F i g u r a { public s t a t i c f i n a l double PI = 3 .8.13 muestra la interface Figura que declara un m´todo para e que las clases que la implementen definan la funcionalidad del c´lculo del ´rea a a de una figura. b u i l d e r . public c l a s s C i r c u l o implements F i g u r a { private double r a d i o . o En particular. 1 2 3 4 5 6 package c o l e c c i o n e s . es muy aconsejable declarar el tipo de los elementos al crear la colecci´n. append ( " C i r c u l o [ r a d i o = " ) .each. cuadrados y tri´ngulos. El Listado 8. 1 4 1 5 9 2 . append ( r a d i o ) . public double g e t A r e a ( ) . la clase ArrayList< E > representa una secuencia indexada de elementos. } Listado 8. el Listado 8. y o se puede acceder a un elementos dentro de la estructura a trav´s de su ´ e ındice. Sin embargo. el Listado e a 8.. b u i l d e r . append ( g e t A r e a ( ) ) . t o S t r i n g ( ) . cada uno de ellos ocupa una posici´n dentro de la estructura. Un ejemplo de c´mo usar las clases colecci´n se muestra en los siguientes o o listados: el Listado 8.. } public C i r c u l o ( double r a d i o ) { this . } @Override public double g e t A r e a ( ) { return PI ∗ r a d i o ∗ r a d i o . public C i r c u l o ( ) { super ( ) .16 define la clase TrianguloRectangulo de cuyas instancias tambi´n podemos e calcular el ´rea. El Listado 8. COLECCIONES 125 este cap´ ıtulo s´lo veremos como trabajar con ellos en el momento de creaci´n de o o las clases y las ventajas que supone el uso de gen´ricos. que fueron introducidos e en la versi´n 5 de Java. el compilador s´lo a o mostrar´ un aviso con el siguiente texto ArrayList is a raw type. b u i l d e r .14 define la clase Circulo de cuyas instancias podemos calcular el ´rea. append ( " ] " ) .

private double a l t u r a . } @Override public S t r i n g t o S t r i n g ( ) { S t r i n g B u i l d e r b u i l d e r = new S t r i n g B u i l d e r ( ) . } @Override public double g e t A r e a ( ) { return b a s e ∗ a l t u r a . return b u i l d e r . append ( " A r e a = " ) . append ( g e t A r e a ( ) ) . public c l a s s R e c t a n g u l o implements F i g u r a { private double b a s e . b u i l d e r .´ 126CAP´ ITULO 8. b u i l d e r . double a l t u r a ) { super ( ) . b u i l d e r . append ( b a s e ) . public T r i a n g u l o R e c t a n g u l o ( ) { super ( ) . public R e c t a n g u l o ( ) { super ( ) . } @Override public double g e t A r e a ( ) { return b a s e ∗ a l t u r a / 2 . t o S t r i n g ( ) . append ( a l t u r a ) . a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package c o l e c c i o n e s . b u i l d e r . this . append ( " T r i a n g u l o R e c t a n g u l o [ a l t u r a = " ) . } @Override public S t r i n g t o S t r i n g ( ) { S t r i n g B u i l d e r b u i l d e r = new S t r i n g B u i l d e r ( ) . base = base . this . private double a l t u r a . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package c o l e c c i o n e s . append ( a l t u r a ) . f i g u r a s . append ( " . this . public c l a s s T r i a n g u l o R e c t a n g u l o implements F i g u r a { private double b a s e . base = base . } public T r i a n g u l o R e c t a n g u l o ( double base . append ( " . b u i l d e r . b u i l d e r . } } Listado 8. b u i l d e r . double a l t u r a ) { super ( ) . } public R e c t a n g u l o ( double base . ALGUNAS CLASES DE UTILIDAD DEL PAQUETE ESTANDAR 29 } Listado 8. altura = altura . b u i l d e r . append ( " ] " ) . append ( " R e c t a n g u l o [ a l t u r a = " ) . b u i l d e r .14: Esta clase representa un c´ ırculo del que se puede calcular su ´rea. . b u i l d e r . altura = altura . this .15: Esta clase representa un rect´ngulo del que se puede calcular su a a ´rea. b a s e = " ) . f i g u r a s . b a s e = " ) .

append ( " A r e a = " ) . base=1.0 Si en el ArrayList< F igura > del Listado 8. public c l a s s P r i n c i p a l 2 { public s t a t i c void main ( S t r i n g [ ] a r g s ) { A r r a y L i s t f i g u r a s = new A r r a y L i s t ( ) . o a o .8. f i g u r a s . p r i n t l n ( f i g u r a ) .0] Area=3. add (new C i r c u l o ( 1 ) ) . 2 ) ) .0. el compilador o o no hubiese detectado el error.16: Esta clase representa un tri´ngulo rect´ngulo del que se puede a a calcular su ´rea.141592 Rectangulo [altura=2. o u t . for ( Object f i g u r a : f i g u r a s ) System .0. } } Listado 8. append ( b a s e ) . for ( Figura f i g u r a : f i g u r a s ) System . . A r r a y L i s t . add (new T r i a n g u l o R e c t a n g u l o ( 1 . COLECCIONES 28 29 30 31 32 33 34 127 builder builder builder builder return } } . builder . f i g u r a s . f i g u r a s . public f i n a l c l a s s P r i n c i p a l { public s t a t i c void main ( S t r i n g [ ] a r g s ) { A r r a y L i s t <F i g u r a > f i g u r a s = new A r r a y L i s t <F i g u r a >() . add (new R e c t a n g u l o ( 1 . a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 package c o l e c c i o n e s . toString () . Listado 8.4. } } Listado 8. u t i l . A r r a y L i s t . append ( " ] " ) . p r i n t l n ( ( F i g u r a ) f i g u r a ) . f i g u r a s . add (new T r i a n g u l o R e c t a n g u l o ( 1 . tal y como muestra o u el Listado 8. 2 ) ) .0 TrianguloRectangulo [altura=2. 2 ) ) .18: Ejemplo de uso de la clase ArrayList sin especificar el tipo de los elementos de la colecci´n. Si no indic´semos el tipo de los datos que o a maneja la colecci´n en el momento de la creaci´n del ArrayList.17 intent´semos a˜adir una a n instancia de una clase que no implementa el interface Figura. o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package c o l e c c i o n e s . f i g u r a s . import j a v a . La ejecuci´n de esta peque˜a aplicaci´n muestra el siguiente resultado: o n o Circulo [radio=1. u t i l . import j a v a . base=1. o u t . add (new C i r c u l o ( 1 ) ) . f i g u r a s . 2 ) ) . obtendr´ ıamos un error en tiempo de compilaci´n. f i g u r a s . f i g u r a s . . .0] Area=1. f i g u r a s . add (new I n t e g e r ( 1 ) ) .18 y el resultado de su ejecuci´n. append ( g e t A r e a ( ) ) . y se producir´ en tiempo de compilaci´n al extraer ıa o el elemento err´neo y modelarlo a la interface com´n Figura. add (new R e c t a n g u l o ( 1 .0] Area=2. Se producir´ un error en tiempo de ejecuci´n.17: Ejemplo de uso de la clase ArrayList< F igura >.

boolean isEmpty(). en particular.0.1.0] Area=3. MMMM para mostrar el nombre ıa . La clase Date La clase Date representa un instante del tiempo con una precisi´n de miliseo gundos. Trabajo con fechas El paquete de clases de utilidad de Java nos proporciona un conjunto de clases para trabajar con fechas y especificar el formato cuando la fecha se muestre como texto. base=1.0 Exception in thread "main" java.sun.figuras.19.html.java:13) Otros m´todos utiles de la clase ArrayList< E > (que comparte con el resto e ´ de clases que implementan la interface List) son: E get(int posicion). o Un sencillo ejemplo de uso de la clase Date se muestra en el Listado 8.figuras. Listado 8. Para trabajar con fee chas. por ejemplo para saber qu´ d´ de la semana ser´ mi pr´ximo cumplea˜os.lang.Principal.ClassCastException: java.5. se puede consultar la documentaci´n de eso ta clase en esta direcci´n http://java.5. todos e a aquellos m´todos relacionados con el trabajo con fechas. Muchos de los m´todos de esta clase est´n obsoletos.Figura at colecciones. o u t . lo que mostrar´ por consola: ıa Ahora: Fri Jul 02 10:19:40 CEST 2010 donde se est´ utilizando un formato anglosaj´n para mostrar la fecha. aqu´ s´lo mostraremos el ejemplo del Listado ı o 8.0] Area=2. int u size().main(Principal. Para una descripci´n de los s´ o ımbolos que se pueden utilizar al especificar el formato. devuelve el n´mero de elementos. void clear() elimina todos los eleo mentos.0 TrianguloRectangulo [altura=2.20. a o 1 System .0] Area=1. La clase SimpleDateFormat nos permite definir el formato con el que queremos mostrar las fechas. Para obtener el instante de tiempo actual. La informaci´n se o almacena como un entero long cuyo origen de tiempos es el 1 de Enero de 1970 a las 00:00:00 horas. devuelve true si no el ArrayList< E > no contiene ning´n elemento y false en caso contrario. ALGUNAS CLASES DE UTILIDAD DEL PAQUETE ESTANDAR Circulo [radio=1. simplemente creamos una instancia de esta clase a partir de su constructor por defecto. donde se est´ utilizando EEEE para mostrar el d´ de la semana. dd para a ıa mostrar el ordinal del d´ dentro del mes. e ıa a o n se utiliza la clase GregorianCalendar tal y como veremos en la Secci´n 8. p r i n t l n ( " A h o r a : " + new Date ( ) ) . de vuelve true si el elementos est´ en a la lista y false en caso contrario.´ 128CAP´ ITULO 8. devuelve el elementos en la posici´n indicada.0.19: Uso de la clase Date para mostrar el instante actual. 8.com/javase/6/docs/api/java/ o text/SimpleDateFormat.2. base=1.5. boolean contains(Object o).Integer cannot be cast to colecciones.lang.141592 Rectangulo [altura=2. u 8.

p r i n t l n ( " A h o r a . por ejemplo. o u t . mm para mostrar los minutos de la hora. G r e g o r i a n C a l e n d a r c a l e n d a r i o = new G r e g o r i a n C a l e n d a r ( ) .5. por lo que no hace falta crear una instancia para poder utilizarlos. a 8. saber qu´ d´ e ıa de la semana ser´ dentro de 40 d´ tal y como muestra el Listado 8. el texto obtenido es: Ahora: viernes 02 de julio de 2010 (10:30:29) 1 2 SimpleDateFormat s d f = new SimpleDateFormat ( " E E E E d d ’ d e ’ M M M M ’ d e ’ y y y y ’( ’ h h ’: ’ m m ’: ’ s s ’) ’ " ) . Todos los m´todos de esta clase e son static. " + s d f . . El Listado 8. Las clases Calendar y GregorianCalendar La clase Calendar nos permite convertir instantes temporales. c a l e n d a r i o . y otras extensiones de esta clase implementan calendarios concretos.2. ´ getTime ( ) ) ) . f o r m a t ( c a l e n d a r i o . System . p r i n t l n ( " A h o r a : " + s d f .22 muestra algunos ejemplos sencillos de las funciones matem´tia cas que proporciona la clase Math.20: Uso de la clase SimpleDateFormat para definir el formato de una fecha como una cadena de texto. Este es el caso de la clase GregorianCalendar que implementa el c´lculo de fechas a en el calendario gregoriano. Listado 8.6. representados por la clase Date. f o r m a t (new Date ( ) ) ) . Esta clase nos permite. minutos. a˜o. sumar una cantidad de d´ a la fecha actual para conocer ıas la nueva fecha Todas las constantes para indicar el d´ mes. a un fecha expresada en d´ meses. o u t . algunas de ellas son la clase Math y la clase Random. 4 0 ) . Matem´ticas a En el paquete est´ndar de Java encontramos algunas clases para hacer c´lculos a a matem´ticos. La clase Calendar es abstracta.21. ıas.´ 8. n segundos. System . etc´tera est´n definidas en la ıa.6. o u t . Listado 8. DAY OF YEAR. 8. Con este formato.6. System . MATEMATICAS 129 del mes completo. por ejemplo. 1 2 3 4 5 SimpleDateFormat s d f = new SimpleDateFormat ( " E E E E d d ’ d e ’ M M M M ’ d e ’ yyyy " ) .21: La clase GregorianCalendar nos permite trabajar con fechas como. La clase Calendar nos proporciona la funcionalidad m´ ınima para trabajar con fechas. getTime ( ) ) ) . y ss para mostrar los segundos dentro del minuto. yyyy para mostrar el a˜o. por lo que no se puede instanciar. f o r m a t ( c a l e n d a r i o . add ( C a l e n d a r . La clase Math La clase Math nos proporciona algunas de las funciones matem´ticas trigoa nom´tricas. hh para mostrar la hora en forn mato 24 horas. e a clase Calendar. logar´ e ıtmicas y otras de utilidad.1. horas. p r i n t l n ( " D e n t r o d e 4 0 d ı a s : " + s d f . 8. a ıas.

Math . ¿C´mo es esto posible siendo la clase Calendar abstracta?. Math . Escribe un programa que calcule la cuota mensual de una hipoteca por el sistema franc´s.4142 ı El logaritmo natural de 2. o u t . Cuestiones. 4 f " . posee el m´todo public static Calendar getInstance() que e devuelve una referencia a Calendar perfectamente funcional y con la que podemos trabajar con fechas como si de la clase GregorianCalendar se tratase. 2 f e s % 1 . p r i n t ( e q u i p r o b a b l e s . f o r m a t ( " E l s e n o d e % 2 . n e x t I n t ( 1 0 0 ) + " . p r i n t l n ( S t r i n g . System . en cuyo caso la secuencia gee nerada sigue una distribuci´n aleatoria de media 0 y desviaci´n est´ndar 1. n e x t G a u s s i a n () ) ) . " ) . o Ejercicios. System . s i n ( Math .000 8.22: Algunas funciones de la clase Math.22 es el siguiente: o El seno de 0. La u secuencia de n´meros es reproducible si al crear la instancia de Random utilizau mos la misma semilla. System . 1. o u t .6. Listado 8.2 f . PI / 4 . 3 f " .23: Secuencias de valores aleatorios generados por la clase Random. E . El resultado de la ejecuci´n del Listado 8. p r i n t l n ( S t r i n g . ALGUNAS CLASES DE UTILIDAD DEL PAQUETE ESTANDAR 1 2 3 System . Math . PI / 4 ) ) ) . El o o a Listado 8. 1 2 3 4 5 6 7 8 Random e q u i p r o b a b l e s = new Random ( ) .23 muestra algunos ejemplos de uso de los m´todos que proporciona e esta clase. o u t . o u t . e q u i p r o b a b l e s . s q r t ( 2 ) ) ) . 1.79 es 0. 3 f " . p r i n t l n ( S t r i n g . i ++) System . i ++) System .718 es 1.2. o u t .707 La ra´z cuadrada de 2 es 1. l o g ( Math . " ) . dada por la siguiente f´rmula: e o mensualidad = capital · n 1 1− n (1 + n)(12·a˜ os) . La clase Random La clase Random genera secuencias aleatorias de n´meros o valores booleanos. p r i n t ( S t r i n g . f o r ( i n t i = 0 . Listado 8. E) ) ) . excepto si utilizamos el m´todo double nextGaussian(). p r i n t l n ( " U n a s e c u e n c i a s a l e a t o r i a g a u s s i a n a d e n ´ m e r o s . i < 1 0 . ı Math . p r i n t l n ( " U n a s e c u e n c i a s a l e a t o r i a e q u i p r o b a b l e d e n ´ m e r o s u entre 0 y 100. " ) . f o r m a t ( " L a r a ´ z c u a d r a d a d e 2 e s % 1 . Math . o u t . Los valores de las secuencias son equiprobables. 3 f e s % 1 . o u t . " . u f o r ( i n t i = 0 . f o r m a t ( " E l l o g a r i t m o n a t u r a l d e % 1 . f o r m a t ( " %. Si lees el API de la clase Calendar observar´s que aunque esta clase es absa tracta.´ 130CAP´ ITULO 8. System . i < 1 0 .

6. . MATEMATICAS donde n = interes . 1200 131 Lecturas recomendadas. El Cap´ ıtulo 17 de la referencia [2] muestra nuevas clases de utilidad.´ 8.

´ 132CAP´ ITULO 8. ALGUNAS CLASES DE UTILIDAD DEL PAQUETE ESTANDAR .

. . . . . . 134 e e Clases gen´ricas . . Comodines . . . que fue introo e ducida en Java en la versi´n 5. . . . .4. 135 e Ampliaci´n del tipo gen´rico . . . .2. 9. .4 vimos c´mo utilizar las clases coo o lecci´n. . .4. . . . Como vimos. una ventaja del uso de gen´ricos o e es asegurar que las referencias con las que trabaja la clase gen´rica son de tipo e compatible con el especificado en el momento de la instanciaci´n de la clase o gen´rica. .2. . a e El concepto de programaci´n con gen´ricos es muy potente. .Cap´ ıtulo 9 Programaci´n con gen´ricos o e Contenidos 9. . 139 9. . error e o que pasar´ desapercibido sin el uso de tipos gen´ricos. 133 e e M´todos gen´ricos . . obtendremos un error en tiempo de compilaci´n. .1. .5. o basta con indicarlo en el momento de instanciar la clase colecci´n. . . . . . Las clases colecci´n son conteo o o nedores de referencias de las que se especifica su tipo en el momento de crear la instancia de la clase colecci´n. . en la secci´n 8. . Los gen´ricos nos permiten definir clases que o e trabajar´n con instancias de objetos de los que no especificamos su tipo en a el momento de la definici´n de la clase. 141 Introducci´n o En este cap´ ıtulo se presenta la programaci´n con gen´ricos. . Vimos la o 133 . . . ıa e 9. ¿Qu´ son los tipos de datos gen´ricos? e e Sin detenernos en detalles. . . y vimos que estas clases pueden trabajar con cualquier tipo de datos. . . 9. . . 139 9. . de lo contrario. . . . . . . . . . . .1. . . . . . . .4 dedicada a las clases colecci´n. . . . . . . . . .1. . . . . . . . . Borrado de tipo y compatibilidad con c´digo heo redado . . . . ¿Qu´ son los tipos de datos gen´ricos? . . . . . . . 9. . . El tipo de las referencias que la clase o manejar´ se especifica en el momento de crear las instancias de la clase gen´rica.3. Tipos gen´ricos con l´ e ımite superior . .4. . . . . . . . . . . . . . . . 138 o e 9. como has visto o e en la secci´n 8. .

1 muestra un ejemplo de un m´todo que trabaja e con un tipo gen´rico. e de modo que la lista de argumentos (T t) se interpreta como una referencia de tipo gen´rico T. El Listado 9. o Al trabajar sin gen´ricos podemos cometer errores (introducir una referencia de e tipo incompatible con el resto de elementos en la colecci´n). unicamente e ´ se indica que se utilizar´ alg´n tipo de dato pero no se indica el tipo concreto a u hasta que no se utiliza.. Los tipos de datos gen´ricos se pueden utilizar en la e definici´n de un m´todo. es o que se sustituye el s´ ımbolo de tipo gen´rico <T> por el tipo concreto (Float) en e . o e o 9. causando graves problemas durante o la ejecuci´n de nuestras aplicaciones. M´todos gen´ricos e e Un m´todo definido en una clase puede trabajar con un tipo gen´rico aunque la e e clase no lo haga.1: Definici´n y uso de un m´todo gen´rico. import t i p o s . en este caso.134 ´ ´ CAP´ ITULO 9. o u t . muestraNombreClase (new P e r s o n a ( ) ) . e Lo que ocurre en el momento de la compilaci´n en el ejemplo anterior. o a Un tipo de datos gen´rico es un tipo de datos que no se especifica. } public s t a t i c void main ( S t r i n g [ ] a r g s ) { MetodoGenerico m e t o d o G e n e r i c o = new MetodoGenerico ( ) .muestraNombreClase(new Float(1)). el tipo gen´rico <T> se sustituye por el tipo particular Float. e 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package g e n e r i c o s . m e t o d o G e n e r i c o . p r i n t l n ( " S o y u n a i n s t a n c i a d e l a c l a s e : " + t . o e e Sintaxis de Java Para indicar que un m´todo trabaja con tipos gen´ricos se escribe < T > entre e e el modificador de acceso y el tipo de dato de retorno del m´todo. o en la definici´n de una clase. El modo de uso es una simple llamada al m´todo como e e por ejemplo metodoGenerico. muestraNombreClase (new F l o a t ( 1 ) ) . de los que no nos o daremos cuenta en tiempo de compilaci´n. PROGRAMACION CON GENERICOS gran ventaja que esto supon´ al no trabajar con referencias a la clase Object ıa que deb´ ıamos modelar al tipo adecuado al extraer los elementos de la colecci´n. F´ e ıjate en la declaraci´n del m´todo private <T>void o e muestraNombreClase(T t). P e r s o n a . public f i n a l c l a s s MetodoGenerico { private MetodoGenerico ( ) { super ( ) . } } Listado 9.2. } private <T> void muestraNombreClase (T t ) { System . m e t o d o G e n e r i c o . getCanonicalName ( ) ) . g e t C l a s s ( ) . la <T> indica que se va a utilizar un tipo gen´rico. El uso de gen´ricos hace posible la deteco e ci´n de estos errores de incompatibilidad de tipos durante la fase de compilaci´n o o haciendo que nuestro c´digo sea m´s robusto. de modo que e el m´todo se reescribe como private void muestraNombreClase(Float t).

de modo que cada medida almacena el valor del dato medido y un comentario descriptivo. Indica Valor. La idea es dejar sin especificar el e tipo de datos que representa la medida tal y como se muestra en el Listado 9. si es necesario indicar e m´s tipos gen´ricos se toman las letras may´sculas que siguen a T. private S t r i n g d e s c r i p c i o n . La convenci´n utiliza las siguientes letras para indicar tipos gen´ricos: o e E. public abstract c l a s s S e n s o r <T> { protected T medida .´ 9. por ejemplo a e u <T. o K.2: La clase Sensor no especifica el tipo de dato que proporciona. S. Indica Clave. etc. Inicialmente no conocemos los tipos de medidas que nos puede devolver un sensor. Ya que la temperatura se puede especificar como un n´mero real. como en el caso de los Mapas. } public f i n a l void s e t D e s c r i p c i o n ( S t r i n g d e s c r i p c i o n ) { this . U> void metodo(T t. como en el caso de las clase Colecci´n. Indica Tipo. V. por lo que no podemos decidir en el momento de la definici´n de la o clase Sensor la naturaleza del dato que representa la medida. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package s e n s o r e s . U. utilizando gen´ricos. Ahora es el momento de crear algunos sensores concretos. ¿C´mo lo podemos o resolver? Evidentemente. Si el m´todo trabaja con un par de tipos gen´ricos que pueden ser diferentes e e se indica como private <T. 9.3. y tambi´n sensores de viento que miden la intensidad y direcci´n e o del viento. CLASES GENERICAS 135 el ejemplo del Listado 9. elegimos la clase Float para representar u . Clases gen´ricas e Supongamos que queremos definir una clase que represente una medida tomada por un sensor. U u). d esc ri pc ion = d esc ri pci on . } public S t r i n g g e t D e s c r i p c i o n ( ) { return d e s c r i p c i o n .1. U>.3. Indica Numero. } } Listado 9. N. Indica Elemento. public T g e t M e d i c i o n ( ) { return medida . como en el caso de los Mapas.2. T. El primer sensor que implementaremos es un sensor de temperaturas. existen sensores de temperatura que miden temperaturas. Convenci´n de codificaci´n o o Se usa la letra <T> para indicar el primer tipo gen´rico. se indica con <T>. V.

PROGRAMACION CON GENERICOS la medida de temperatura de modo que nuestra clase SensorTemperatura la podemos definir tal y como muestra el Listado 9. d i r e c c i o n = new D i r e c c i o n ( vx . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package s e n s o r e s . f l o a t vy . private Random t e m p e r a t u r a = new Random ( ) . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package s e n s o r e s . } } Listado 9. } public double g e t I n t e n s i d a d ( ) { return i n t e n s i d a d .3: La clase SensorTemperatura define un sensor capaz de registrar temperaturas representadas como Float Para que se vea con mayor claridad el uso de gen´ricos. Random . vx = vx . import j a v a . vamos a completar el e ejemplo definiendo un nuevo sensor. public D i r e c c i o n ( f l o a t vx .136 ´ ´ CAP´ ITULO 9. public c l a s s D i r e c c i o n { f l o a t vx . ya que este tiene intensidad y direcci´n.4. n e x t F l o a t ( ) ) . } public V e l o c i d a d V i e n t o ( f l o a t i n t e n s i d a d . esta vez un sensor de velocidad del viento capaz de tomar datos de la intensidad y direcci´n del viento. tal y como muestra el Listado 9. private D i r e c c i o n d i r e c c i o n .3. setDescripcion () . u t i l . vy ) . public c l a s s V e l o c i d a d V i e n t o { private f l o a t i n t e n s i d a d . } } public V e l o c i d a d V i e n t o ( ) { super ( ) . as´ que definimos una nueva o ı clase que represente la medida de la velocidad del viento. public S e n s o r T e m p e r a t u r a ( ) { super ( ) . t h i s . } public f i n a l void s e t D e s c r i p c i o n ( ) { super . medida = new F l o a t (TEMPERATURA MAXIMA∗ t e m p e r a t u r a . f l o a t vy ) { . s e t D e s c r i p c i o n ( " D a t o d e t e m p e r a t u r a e n g r a d o s C e l s i u s " ) . } public D i r e c c i o n g e t D i r e c c i o n ( ) { f l o a t vx . t h i s . Esta vez ning´n o u tipo de dato primitivo nos sirve para representar la medida de la velocidad del viento. intensidad = intensidad . " + vy + " ] " . this . public c l a s s S e n s o r T e m p e r a t u r a extends S e n s o r <F l o a t > { private s t a t i c f i n a l f l o a t TEMPERATURA MAXIMA = 4 5 . vy = vy . } f l o a t vy ) { public S t r i n g t o S t r i n g ( ) { return " [ " + vx + " .

" ) .3. En ambos casos de sensores. private Random v i e n t o = new Random ( ) . f l o a t s e n o = ( f l o a t ) ( Math . Finalmente. y este no se modifica durante la ejecuci´n de la aplicaci´n. la definici´n de un sensor de velocidad del viento es la o mostrada en el Listado 9. Cuando o o veamos en el Cap´ ıtulo 14 c´mo trabajar con Hilos en Java. reescribiremos el o c´digo de esta aplicaci´n para que sea m´s realista. un ejemplo del o o a uso de estas clase se muestra en el Listado 9. f l o a t c o s e n o = ( f l o a t ) ( Math . System . o } private f i n a l void s e t M e d i d a ( ) { f l o a t a n g u l o = ( f l o a t ) ( v i e n t o . p r i n t l n ( " T e m p e r a t u r a : " + s e n s o r T . o Con esta nueva clase. } } Listado 9. import j a v a .6. } public f i n a l void s e t D e s c r i p c i o n ( ) { super . coseno ) .5: La clase SensorVelocidadVieto define un sensor capaz de registrar la velocidad del viento.5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package s e n s o r e s . PI ) . S e n s o r V e l o c i d a d V i e n t o .4: La clase VelocidadVieto define una clase que almacena la intensidad y la direcci´n de una medida del viento. setDescripcion () . estamos generando de modo aleatorio el valor del dato le´ ıdo. public S e n s o r V e l o c i d a d V i e n t o ( ) { super ( ) . s e t D e s c r i p c i o n ( " M i d e l a v e l o c i d a d y d i r e c c i ´ n d e l v i e n t o . c o s ( a n g u l o ) ) . public f i n a l c l a s s P r i n c i p a l { private P r i n c i p a l ( ) { super ( ) . u t i l .´ 9. o u t . D i r e c c i o n . } private void e j e c u t a ( ) { S e n s o r T e m p e r a t u r a s e n s o r T = new S e n s o r T e m p e r a t u r a ( ) . import s e n s o r e s . g e t M e d i c i o n ( ) ) . S e n s o r T e m p e r a t u r a . medida = new V e l o c i d a d V i e n t o (VELOCIDAD MAXIMA∗ v i e n t o . Random . 1 2 3 4 5 6 7 8 9 10 11 12 13 package p r i n c i p a l . import s e n s o r e s . n e x t F l o a t ( ) ∗ Math . V e l o c i d a d V i e n t o . } @Override public S t r i n g t o S t r i n g ( ) { return " I n t e n s i d a d : " + i n t e n s i d a d + " D i r e c c i ´ n : " + d i r e c c i o n . . s i n ( a n g u l o ) ) . seno . CLASES GENERICAS 35 36 37 38 39 40 41 42 137 return d i r e c c i o n . setMedida ( ) . n e x t F l o a t ( ) . import s e n s o r e s . o } } Listado 9. public c l a s s S e n s o r V e l o c i d a d V i e n t o extends S e n s o r <V e l o c i d a d V i e n t o > { private s t a t i c f i n a l f l o a t VELOCIDAD MAXIMA = 1 0 0 .

8. podr´ e o ıamos a˜adir a la lista de c´ n ırculos cualquier otra figura a trav´s de la referencia figuras.7.6 es: o o Temperatura: 1. Si pudi´semos hacer la asignaci´n. Sabemos que la claa a se ArrayList<E> es un contenedor que trabaja con gen´ricos. PROGRAMACION CON GENERICOS S e n s o r V e l o c i d a d V i e n t o s e n s o r V = new S e n s o r V e l o c i d a d V i e n t o ( ) .4107025 Viento: Intensidad: 40. Listado 9. // ERROR ! ! ! Listado 9.138 14 15 16 17 18 19 20 21 22 ´ ´ CAP´ ITULO 9. retomee mos el ejemplo de la Secci´n 8.831844 Direcci´n: [0. c i r c u l o s . a a 9. o u t . tal y como muestra el Listado 9. -0. g e t M e d i c i o n ( ) ) . f i g u r a s . System . e .6: Este listado muestra c´mo usar los sensores los tipos de sensores o anteriormente definidos.7000265. p r i n t l n ( " V i e n t o : " + s e n s o r V . t r i ´ n g u l o s r e c t a n g u l o s y r e c t a n g u l o s s on f i g u r a s . // f i g u r a s = c i r c u l o s . Ahora creamos una lista s´lo para almacenar c´ o ırculos. y autom´ticamente ser´ capaz de devolvernos el dato que mide. Un ejemplo del resultado de la ejecuci´n del c´digo del Listado 9. 1 2 3 4 5 6 // Una l i s t a de f i g u r a s . aunque la clase Circulo implemente el interface Figura.4. ı a ´ ´ f i g u r a s . 7 8 9 10 11 // Ahora un A r r a y L i s t s o l o de c´ r c u l o s ´ ı A r r a y L i s t <C i r c u l o > c i r c u l o s = new A r r a y L i s t <C i r c u l o >() . no podemos o asignar a un ArrayList<Figuras> un ArrayList<Circulo>. // C´r c u l o s . principal . tri´ngulos rect´ngua a los y rect´ngulos de las que podemos calcular su ´rea. ejecuta () . f i g u r a s . en la l´ ınea de c´digo 11 hay un error. luego podemos e crear un ArrayList<Figura> para almacenar en ´l cualquier tipo de figura que e se pueda dibujar. podemos crear cualquier tipo de sensor extendiendo a la clase Sensor. intentamos asignar a la lista de figuras figuras la lista que s´lo almacena c´ o ırculos circulos. basta definir el tipo de dato que mide el sensor.4 de las figuras: c´ o ırculos. add (new T r i a n g u l o R e c t a n g u l o ( ) ) .7: Una lista de figuras. ya que la clase Circulo implementa el interface Figura. la conversi´n de tipos no es posio ble. add (new C i r c u l o ( 3 ) ) . Ampliaci´n del tipo gen´rico o e Para seguir profundizando en las posibilidades de los tipos gen´ricos.7141168] o Siguiendo el mismo esquema.8: Una lista de c´ ırculos. add (new C i r c u l o ( ) ) . add (new C i r c u l o ( 5 ) ) . A r r a y L i s t <F i g u r a > f i g u r a s = new A r r a y L i s t <F i g u r a >() . c i r c u l o s . } } Listado 9. } public s t a t i c void main ( S t r i n g [ ] a r g s ) { P r i n c i p a l p r i n c i p a l = new P r i n c i p a l ( ) . Para nuestra sorpresa. add (new R e c t a n g u l o ( ) ) . y una vez creada. tal y como muestra el Listado 9.

El motivo es el mismo que antes. construcci´n significa un ArrayList de cualquier tipo que implemente (o exo tienda) a Figura. pero obtendremos a el mismo error que en el Listado 9. 9. p r i n t l n ( e l e m e n t o .1. De este modo podemos restringir los tipos concretos de las clases gen´ricas.10 estamos restringiendo el tipo concreto de la clase gen´rica a e alg´n tipo que extienda.4. getArea ( ) ) . a la referencia figurasGeneral s´ que le podemos ı asignar cualquier otro ArrayList de tipos concretos si esos tipos implementan . es decir. } } Listado 9. g e t C l a s s ( ) . Comodines La l´ ınea 13 del Listado 9.´ ´ 9. 22 23 24 25 26 private <E extends F i g u r a > void m u e s t r a A r e a s 2 ( A r r a y L i s t <E> l i s t a ) { for ( Figura elemento : l i s t a ) { System . <E extends Figura> indica que los elementos que se pueden e almacenar en la colecci´n pueden ser de cualquier subtipo de Figura. getCanonicalName ( ) + " : " + elemento . getCanonicalName ( ) + " : " + elemento . Tipos gen´ricos con l´ e ımite superior El Listado 9. g e t C l a s s ( ) .9. el tipo ArrayList<Figura> es diferente al tipo ArrayList<Circulo>.4. o u t .2. getArea ( ) ) . p r i n t l n ( e l e m e n t o . podemos llamar a este m´todo con cualquier e ArrayList<T> siempre que sus elementos implementen la interface Figura. o implemente.10: Un m´todo que recibe una lista gen´rica de elementos que e e implementan la interface Figura.8 si lo intentamos con la referencia circulos. el tipo Figura. 20 21 22 23 24 private void m u e s t r a A r e a s ( A r r a y L i s t <F i g u r a > l i s t a ) { for ( Figura elemento : l i s t a ) { System . u 9.10 muestra un m´todo en el que se da un l´ e ımite superior al tipo de datos gen´rico. e En el Listado 9. AMPLIACION DEL TIPO GENERICO 139 Si intentamos escribir un m´todo capaz de mostrar el ´rea de todas las figuras e a de una lista tal y como muestra el Listado 9. F´ o ıjate que aunque Figura es una interface se utiliza la palabra reservada extends y no implements. los tipos gen´ricos con l´ o e ımite superior. no tendremos ning´n error cuando u mostremos las ´reas de las figuras de la referencia figuras. o u t .9: Un m´todo que recibe una lista de elementos de tipo interface e Figura. donde ? es un comod´ Esta ın.4. ¿C´mo podemos resolver esta encrucijada? ¿C´mo podemos indicar que queo o remos una lista de cualquier cosa que implemente la Figura para poder asignar a una lista de figuras unas veces listas de s´lo c´ o ırculos y otras veces listas de s´lo rect´ngulos? o a Java nos da una soluci´n para este caso. De este modo.11 presenta una nueva construcci´n del lenguaje: o ArrayList<? extends Figura>figurasGeneral. } } Listado 9.

. con independencia a del tipo de elementos con el que se defini´ la lista tal y como muestra el Listado o 9. 12 13 14 15 16 17 // Una l i s t a con l´ m i t e s u p e r i o r ı A r r a y L i s t <? extends F i g u r a > f i g u r a s G e n e r a l = c i r c u l o s . como en este caso. El m´todo e private void muestraAreas3(ArrayList<? extends Figura>lista). n e No podemos escribir algo como figurasGeneral. por si esto nos pudiera interesar. add (new R e c t a n g u l o ( 1 . 2 ) ) . PROGRAMACION CON GENERICOS (o extienden) el interface Figura. y no hemos utilizado el l´ ımite superior en la restricci´n o de tipo <E extends Figura> como en el caso del Listado 9. g e t C l a s s ( ) . de modo que podemos reescribir el m´todo del Listado 9. A r r a y L i s t <R e c t a n g u l o > r e c t a n g u l o s = new A r r a y L i s t <R e c t a n g u l o >() . En este caso la sintaxis de la construcci´n se muestra en el Listado o 9. getCanonicalName ( ) + " : " + elemento . f´ ıjate que aunque. las clases finales implementan un interfaz. p r i n t l n ( e l e m e n t o .12.9 para e mostrar el ´rea de todas las figuras contenidas en la lista. r e c t a n g u l o s . dicho de otro modo se utiliza siempre extends con el significado de subtipo sea este por extensi´n (extends) o por implementaci´n o o (implements) de una interface.140 ´ ´ CAP´ ITULO 9. o ¿Para qu´ nos sirve entonces esta posibilidad? Aunque no podamos a˜adir e n nuevos elementos a esta lista. figurasGeneral = rectangulos . add (new R e c t a n g u l o ( ) ) .13. 28 29 30 31 32 private void m u e s t r a A r e a s 3 ( A r r a y L i s t <? extends F i g u r a > l i s t a ) { for ( Figura elemento : l i s t a ) { System . r e c t a n g u l o s . } } Listado 9. De modo an´logo. ınea 13 como 17 podemos hacer la asignaci´n. podemos indicar que una clase gen´rica trabaja con rea e ferencias de cualquier clase padre de una clase dada. es capaz de mostrar el ´rea de los elementos de cuala quier lista de figuras. Es importante no olvidar esta restricci´n. 1 A r r a y L i s t <? super C i r c u l o > o t r a L i s t a .13: El tipo de esta clase puede ser cualquier padre de la clase Circulo. Listado 9. y este es que no podemos a˜adir elementos al ArrayList a trav´s de la referencia figurasGeneral. s´ que podemos trabajar con los elementos que ı hay en ella.add(new Circulo().11: Con el uso de comodines podemos definir listas de tipos que extiendan la interace Figura Ahora s´ tanto en la l´ ı. Pero o debemos pagar un precio por esta nueva posibilidad. Listado 9.12: Un m´todo que recibe una lista gen´rica de elementos que e e implementan la interface Figura utilizando comodines. el ArrayList utiliza la palabra reservada extends.10. o u t . getArea ( ) ) . De nuevo.

Sin embare go.com/docs/books/tutorial/extra/ o generics/index. Borrado de tipo y compatibilidad con c´dio go heredado Como has podido ver.5. existe un problema de incompatibilidad con c´digo heredado anterior a la o versi´n 5 de Java en las que no existen tipos gen´ricos.sun. Lecturas recomendadas. es decir. y un sensor de color que mida colores.html puedes encontrar otra interesante y detallada referencia. En este ultimo o e ´ caso.10 en el c´digo se llama una o e o vez con un ArrayList<Circulo> y otra vez con un ArrayList<Recttangulo>. BORRADO DE TIPO Y COMPATIBILIDAD CON CODIGO HEREDADO141 9. 2. Crea otros tipos de sensores.html puedes encontrar la referencia b´sica de Sun soa bre el uso de gen´ricos en Java. o e . En esta direcci´n http://java.´ 9. si el m´todo del Listado 9.sun. e En esta direcci´n http://java. Crea una clase gen´rica Garage que permita almacenar en ellas cualquier e tipo de veh´ ıculos Coches. ¿C´mo se resuelve? de o e o uno modo transparente para el programador. se crean dos versiones de este m´todo con cada uno de estos dos tipos concretos. 1. de Gilad Bracha. es una ubicaci´n especificada por un n´mero real (como la plaza de garage) o el DNI o u del usuario especificado como un String. elige el espacio de colores RGB. Furgonetas y Motos por ejemplo.5. o e todas las clases del Java Collection Framework usan tipos gen´ricos. e Ejercicios. por ejemplo un sensor de presi´n que mida la o presi´n atmosf´rica. de hecho. a la programaci´n con gen´ricos en Java. e A esta t´cnica se la llama Borrado de tipo.com/docs/books/tutorial/java/ o generics/index. la programaci´n con gen´ricos es muy potente. el compilador de Java sustituye los tipos gen´ricos por verdaderos tipos cuando se determinan estos en tiempo e de compilaci´n.

142 ´ ´ CAP´ ITULO 9. PROGRAMACION CON GENERICOS .

. . . . . . . . . . . . . Eclipse ha sido el IDE que hemos elegido. . . . . existen otros excelentes entornos de desarrollo. . . Propiedades . . . 148 .2. . . . . . . Ejecuci´n y limpieza . o 10. y del mismo modo. . . . . 146 . c´mo empaquetar nuestro c´digo y c´mo realizar pruebas sobre o o o o nuestro c´digo con JUnit. Sabemos c´mo compio lar nuestro c´digo. . . Estructuras path-like . 10. . . . . .8. . . 144 . 145 . . . . . 10. . . . o Todas estas tareas han necesitado nuestra intervenci´n. . . 144 . . . . . La elecci´n entre unos y otros acaba siendo cuesti´n de gustos y adaptaci´n m´s o o o a 1 Neatbeans se puede descargar para su instalaci´n desde http://netbeans. . . . . . . . . .3. hemos utilizado un entorno de desarrollo integrado. .2. . . . 151 Introducci´n o Hasta ahora. . . . . . para ejecutar el c´dio o go de nuestra aplicaci´n hemos tenido que pulsar el bot´n correspondiente en o o Eclipse. . . 150 . para realizar todas las tareas relativas a nuestro proyecto. . . . . . c´mo generar la documentaci´n con javadoc. . . . .4. . . . .Cap´ ıtulo 10 Construcci´n de proyectos o con Ant Contenidos 10. . . . . . . c´mo ejecutar o o o o nuestro c´digo. . . .1. . 151 . . . . . . . o o 10. . . . . como por ejemplo NetBeans1 . . . Qu´ es Ant . . . . . 10. 147 . Objetivos .2. . . .6. Generaci´n de la documentaci´n .1. hemos tenido que actuar sobre el IDE para ejecutar las pruebas unitarias. Tareas . . .9. . . . . . . . . e 10. . . . pero como ya hemos comentado. . .7. .5. . . Definici´n del proyecto . 146 . o 10. . o 10. . . . 10. . o . . . . Empaquetado de la aplicaci´n . . 145 . o 10. . . .2. Ejecuci´n de las Pruebas Unitarias . . . . . . . como Eclipse.org/ o 143 . Compilar el c´digo fuente de un proyecto . . . . . . . . . . .

ya que todos ellos proporcionan una funcionalidad parecida.xml.xml. Incluso el o o modo en que el entorno de desarrollo organiza las carpetas del proyecto puede cambiar. podemos realizar. Pero su utilidad no se o detiene ah´ con Ant podemos hacer mucho m´s que simplemente compilar el ı. la generaci´n de o o o informes a partir de los resultados de las pruebas. el modo de ejecutar una aplicaci´n. Si este o est´ndar tecnol´gico no te es familiar. su p´gina web est´ repleta de informaci´n con respecto a estos est´ndares tecnol´gicos.1. de modo autom´tico. interesa que antes de seguir adelante coa o nozca esta tecnolog´ En esta direcci´n http://www. de e modo que incluso podemos definir nuestras propias tareas. o core encontrar´s una introducci´n a esta tecnolog´ proporcionada por el World a o ıa Wide Web Consortium. con independencia del entorno de desarrollo. el fichero de descripci´n del proyecto es un fichero xml. o el modo de lanzar la herramienta de documentaci´n cambia.org. larg´ o ısimo etc´tera. ya que Ant est´ esa crito en Java. la generaci´n de la documeno taci´n de nuestro proyecto y un largo. o a a a . Ant es un proyecto de la Fundaci´n Apache que puedes encontrar en esta o direcci´n http://ant. a La herramienta de construcci´n de proyectos Ant nos proporciona precio samente eso. al menos. En cada uno de estos entorno de desarrollo.org/standards/xml/ ıa. Ant es extensible. Al igual a a o a o que la p´gina web de Sun sobre Java es la referencia b´sica en la web sobre el lenguaje de a a programaci´n Java.2. Ser´ interesante que. o incluso ıa si no utiliz´semos ning´n entorno de desarrollo. suficiente para lo que nosotros necesitamos en este momento. Dentro del proyecto de conversi´n de temperaturas crea un fichero y ll´mao a lo build. Qu´ es Ant e Ant es una herramienta de construcci´n de proyectos. Estos peque˜os n cambios hacen necesaria la intervenci´n del desarrollador para migrar proyectos o de un entorno a otro. 10. donde tambi´n se encuentran los sencillos o e detalles de instalaci´n. el consorcio que se encarga de los est´ndares Web2 a 2 Este organismo es el encargado del proceso de estandarizaci´n de las tecnolog´ o ıas Web. basta con descomprimir el fichero que se puede descargar o desde la p´gina web de la Fundaci´n Apache y establecer las correspondientes a o variables de entorno. Como ejemplo de uso de Ant. un entorno puede usar el nombre src y otro source. fuese posible realizar las tareas a u comunes sobre un proyecto Java de modo est´ndar. la p´gina web del W3C es la referencia b´sica para los est´ndares web.apache. vamos a utilizar el proyecto de conversi´n de temperaturas presentado en el Cap´ o ıtulo 5 y las pruebas unitarias sobre este proyecto presentadas en el Cap´ ıtulo 6. a c´digo de nuestro proyecto. otras muo a chas tareas como la ejecuci´n de prueba sobre nuestro c´digo.w3. o incluso poder trabajar directamente sobre nuestro proyecto desde consola. un modo de trabajar con nuestros proyectos con independencia del entorno de desarrollo elegido. 10.144 ´ CAP´ ITULO 10. CONSTRUCCION DE PROYECTOS CON ANT que de la funcionalidad que los entornos proporcionan. Definici´n del proyecto o La definici´n de un proyecto Ant siempre se hace en un fichero llamado o build.

o Si la sintaxis xml no te es familiar.2.</ e c h o> 4 </ t a r g e t> 5 </ p r o j e c t> 1 2 Listado 10. Veamos c´mo se especifican las tareas pertenecientes a un objetivo. f´ ıjate que la etiqueta de apertura <project> est´ cerrada con la etiqueta </project>3 . Tareas En Ant existe una enorme cantidad de tareas predefinidas.2: Definici´n de un objetivo Ant.2. El Listado 10.. y como ejemplo. a Un proyecto Ant est´ formado. el nombre del objetivo. 3 En un fichero xml bien formado toda etiqueta abierta debe estar cerrada con su correspondiente etiqueta. En este a momento. <p r o j e c t name=" C o n v e r s i o n T e m p e r a t u r a s "> <t a r g e t name=" e m p e z a n d o "> 3 . o 10.2. 4 </ t a r g e t> 5 </ p r o j e c t> 1 2 Listado 10. por ejemplo. De nuevo. tal y como muestra el Listado 10. existe una tarea para compilar el c´digo fuente de nuestra aplicaci´n. cada objetivo debe ir cerrado con su correspondiente etiqueta de cierre tal y como muestra el Listado 10.3. Objetivos Para definir un objetivo utilizamos la etiqueta <target> que de nuevo tiene un atributo obligatorio. 3 </ p r o j e c t> 1 2 Listado 10. o Cada uno de los objetivos contiene una o m´s tareas que se ejecutar´n en a a el orden en que fueron definidas cuando ejecutemos el correspondiente objetivo.2.1. por uno o m´s objetivos.1 muestra la definici´n b´sica de un proyecto. y otra tarea o o para crear un fichero jar a partir del c´digo compilado de nuestra aplicaci´n.1: Definici´n de un proyecto Ant.. <p r o j e c t name=" C o n v e r s i o n T e m p e r a t u r a s "> <t a r g e t name=" e m p e z a n d o "> 3 <e c h o>Empezando con Ant . y cada uno de estos a a objetivos puede estar formado por una o m´s tareas..´ 10. Cada tarea se realizar´n en a a el orden en el que fue especificada dentro del objetivo.2. vamos a utilizar una tarea muy sencilla cuya funci´n o es simplemente mostrar un mensaje de texto en consola. A o o lo largo de este cap´ ıtulo iremos describiendo las tareas m´s utilizadas.3: La tarea <echo> muestra un mensaje de texto por consola. Veamos c´mo se define o un objetivo en Ant. o a <p r o j e c t name=" C o n v e r s i o n T e m p e r a t u r a s "> . DEFINICION DEL PROYECTO 145 La etiqueta ra´ bajo la cual se define todo el proyecto es <project> que tiene ız un atributo obligatorio name con el que especificamos el nombre del proyecto.. . 10.

xml./excepciones/build/project/classes. lo que invocar´ la ejecuci´n del objetivo empezando definido en el a o fichero build. o podemos utilizar las propiedades que nos permiten asociar a un nombre un valor. 10.3. / e x c e p c i o n e s / b u i l d / c l a s s e s " /> 6 </ t a r g e t> 7 </ p r o j e c t> 1 2 Listado 10. F´ ıjate que previamente a la tarea de compilaci´n de la l´ o ınea 3.4. Compilar el c´digo fuente de un proyecto o La etiqueta <javac> nos permite compilar c´digo Java. CONSTRUCCION DE PROYECTOS CON ANT Ejecutar un objetivo desde l´ ınea de instrucciones es muy sencillo. 1 2 <p r o j e c t name=" C o n v e r s i o n T e m p e r a t u r a s "> < !−− D i r e c t o r i o d e l c o d i g o f u e n t e −− ´ > ..xml y teclear ant empezando. tal y como muestra el Listado 10.. tendremos que cambiar todas la ocurrencias del destino original.xml.4: Compilar un proyecto usando Ant. e indicar donde se escribir´n los ficheros de clases compilados a mediante el atributo destdir. a otro directorio como por ejemplo . y hacer referencia al valor a trav´s de su nombre en cualquier lugar del fichero e build.146 ´ CAP´ ITULO 10. . o a ´ 10. El Listado 10. y es que si decidimos cambiar el fichero de destino de los ficheros compilados por ejemplo desde el original . BUILD SUCCESSFUL Total time: 0 seconds Pasemos a ver c´mo utilizar algunas otras tareas m´s utiles que <echo>. El resultado de la ejecuci´n ser´ parecido a: o a Rayuela:ant oscar$ ant empezando Buildfile: build.xml empezando: [echo] Empezando con Ant. <p r o j e c t name=" C o n v e r s i o n T e m p e r a t u r a s "> <t a r g e t name=" c o m p i l e " d e s c r i p t i o n=" C o m p i l a e l p r o y e c t o "> 3 <mkdir d i r=" . / e x c e p c i o n e s " 5 d e s t d i r=" . Propiedades El objetivo compile tal y como lo hemos descrito tiene un inconveniente.5. ./excpeciones/build/classes. bien desde la vista Ant de Eclipse. basta situarse en el directorio donde se encuentre el fichero build. hemos utilizado la tarea mkdir para crear el directorio de destino de las clases compiladas.4 muestra el uso de la etiqueta <javac>. Para poder usar esta o etiqueta debemos indicar el directorio donde est´ el c´digo fuente mediante el a o atributo srcdir. Para solucionar esta situaci´n. Ahora ya puedes compilar el c´digo de tu proyecto invocando al objetivo o compile bien desde consola. / e x c e p c i o n e s / b u i l d / c l a s s e s " /> 4 <j a v a c s r c d i r=" . .

y nos permiten u a definir grupos de directorios o ficheros. d i r } " d e s t d i r=" $ { t e s t . d i r " l o c a t i o n=" $ { b u i l d .t e s t s " depends=" c o m p i l e " d e s c r i p t i o n=" C o m p i l a l o s t e s t s . d i r " l o c a t i o n=" . <p r o j e c t name=" C o n v e r s i o n T e m p e r a t u r a s "> < !−− D i r e c t o r i o d e l c o d i g o f u e n t e −− ´ > 3 <p r o p e r t y name=" s r c .6 muestra el uso de esta etiqueta con el objetivo de compilar las clases de pruebas unitarias. . d i r " l o c a t i o n=" \ $ { b u i l d . c l a s s e s . ESTRUCTURAS PATH-LIKE 3 4 5 6 7 8 9 147 <p r o p e r t y name=" s r c . adem´s del directorio donde se encuentran las clases de prueba que queremos a compilar. En este caso. j a r " /> <p a t h e l e m e n t l o c a t i o n=" \ $ { b u i l d . "> <mkdir d i r=" $ { t e s t . cada una de las propiedades hace referencia a una direcci´n o representada por el atributo location. c l a s s e s . c o m p i l e . d i r " l o c a t i o n=" . d i r } " /> <j a v a c s r c d i r=" $ { t e s t . . c l a s s e s . d i r } " /> </ path> <t a r g e t name=" c o m p i l e " d e s c r i p t i o n=" C o m p i l a e l p r o y e c t o "> <mkdir d i r=" $ { b u i l d . d i r } " /> 13 </ t a r g e t> 14 </ p r o j e c t> 10 Listado 10. Estructuras path-like Con las propiedades podemos definir valores a los que poder hacer referencia por su nombre. d i r " l o c a t i o n=" . d i r } " /> </ t a r g e t> <t a r g e t name=" c o m p i l e .5. tenemos programadas una serie de o o clases de pruebas unitarias que necesitamos compilar antes de ejecutar. d i r } " d e s t d i r=" $ { b u i l d . d i r " l o c a t i o n=" \ $ { b u i l d .5: Uso de las propiedades. d i r " l o c a t i o n=" b u i l d " /> 6 < !−− S u b d i r e c t o r i o de l a s c l a s e s c o m p i l a d a s d e l p r o y e c t o −− > 7 <p r o p e r t y name=" b u i l d . d i r } / c l a s s e s " /> <t a r g e t name=" c o m p i l e " d e s c r i p t i o n=" C o m p i l a e l p r o y e c t o "> <mkdir d i r=" $ { b u i l d . d i r } " 12 d e s t d i r=" $ { b u i l d . d i r } " /> 11 <j a v a c s r c d i r=" $ { s r c . d i r } "> . c l a s s e s . d i r " l o c a t i o n=" b u i l d " /> < !−− S u b d i r e c t o r i o de l a s c l a s e s c o m p i l a d a s d e l p r o y e c t o −− > <p r o p e r t y name=" b u i l d . en nuestro proyecto de la aplicaci´n de conversi´n de temperaturas. Para definir grupos de directorios y ficheros Ant nos proporciona la etiqueta <path>. / l i b " /> 1 2 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <path i d=" t e s t . Para compilar las clases de pruebas unitarias necesitaremos la biblioteca junit. d i r } / c l a s s e s " /> 8 < !−− D i r e c t o r i o de l a s c l a s e s de prueba −− > 9 <p r o p e r t y name=" t e s t . c l a s s e s .10. 10. / t e s t / t e s t " /> 10 < !−− S u b d i r e c t o r i o de l a s c l a s e s c o m p i l a d a s de prueba −− > 11 <p r o p e r t y name=" t e s t . El Listado 10. / e x c e p c i o n e s " /> < !−− D i r e c t o r i o de c l a s e s c o m p i l a d a s −− > <p r o p e r t y name=" b u i l d .c l a s s e s " /> 12 < !−− D i r e c t o r i o de b i b l i o t e c a s d e l p r o y e c t o −− > 13 <p r o p e r t y name=" l i b " l o c a t i o n=" . . c l a s s e s . c l a s s e s . d i r } / t e s t . c l a s s e s . c l a s s e s . c l a s s e s .5. . Por ejemplo. Las estructuras path-like son a´n m´s potentes. d i r } " /> <j a v a c s r c d i r=" \ $ { s r c .jar. / e x c e p c i o n e s " /> 4 < !−− D i r e c t o r i o de c l a s e s c o m p i l a d a s −− > 5 <p r o p e r t y name=" b u i l d . c l a s s p a t h "> < f i l e s e t d i r=" $ { l i b } " i n c l u d e s=" * .

6. d i r " l o c a t i o n=" . CONSTRUCCION DE PROYECTOS CON ANT r e f i d=" t e s t . F´ ıjate en la l´ ınea 27. d i r " l o c a t i o n=" $ { r e p o r t s . a Por su lado. d i r " l o c a t i o n=" \ $ { b u i l d . . las clases a probar deben estar previamente compiladas. Finalmente. .6 estamos definiendo las propiedades que hacen referencia al directorio con el c´digo fuente de las clases de prueba. d i r } / c l a s s e s " /> 8 < !−− D i r e c t o r i o de l a s c l a s e s de prueba −− > 9 <p r o p e r t y name=" t e s t . c l a s s e s .jar y harmcret. en esa l´ ınea estamos indicando que el objetivo compile-test depende de la tarea compile. estamos definiendo donde est´n las bibliotecas necesarias para compilar las clases a de prueba (junit. c l a s s p a t h "> < f i l e s e t d i r=" $ { l i b } " i n c l u d e s=" * . d i r } " /> </ path> <t a r g e t name=" c o m p i l e " d e s c r i p t i o n=" C o m p i l a e l p r o y e c t o "> .jar) y donde est´n las clases compiladas del a proyecto. c o m p i l e . c o m p i l e . d i r " l o c a t i o n=" r e p o r t s " /> 16 < !−− D i r e c t o r i o p a r a l o s i n f o r m e s en f o r m a t o t e x t o −− > 17 <p r o p e r t y name=" r e p o r t s . d i r " l o c a t i o n=" . d i r } / t e s t . / l i b " /> 14 < !−− D i r e c t o r i o de i n f o r m e s −− > 15 <p r o p e r t y name=" r e p o r t s . entre las l´ ıneas 26-34 estamos definiendo un objetivo para compilar las clases de prueba. c o m p i l e . d i r " l o c a t i o n=" \ $ { b u i l d . para poder compilar las clases de prueba. mediante una estructura path-like.148 32 33 ´ CAP´ ITULO 10. 10.6: Uso de estructuras path-like para definir la ruta a las bibliotecas del proyecto. 11 y 13 del Listado 10. mediante el atributo depends de la etiqueta target se fuerza a cubrir los objetivos especificados en antes de cubrir el objetivo actual. <p r o j e c t name=" C o n v e r s i o n T e m p e r a t u r a s " d e f a u l t=" t e s t "> < !−− D i r e c t o r i o d e l c o d i g o f u e n t e −− ´ > 3 <p r o p e r t y name=" s r c . j a r " /> <p a t h e l e m e n t l o c a t i o n=" $ { b u i l d . c l a s s e s . Evidentemente. d i r } / t x t " /> 1 2 18 19 20 21 22 23 24 25 26 27 28 29 30 31 < !−− Path p a r a c o m p i l a r l a s c l a s e s de prueba −− > <path i d=" t e s t . En las l´ ıneas 9. t x t . d i r " l o c a t i o n=" b u i l d " /> 6 < !−− S u b d i r e c t o r i o de l a s c l a s e s c o m p i l a d a s d e l p r o y e c t o −− > 7 <p r o p e r t y name=" b u i l d . c l a s s e s . c l a s s p a t h "> <path r e f i d=" t e s t . . / t e s t / t e s t " /> 10 < !−− S u b d i r e c t o r i o de l a s c l a s e s c o m p i l a d a s de prueba −− > 11 <p r o p e r t y name=" t e s t . d i r } " /> </ path> < !−− Path p a r a e j e c u t a r l a s c l a s e s de prueba −− > <path i d=" t e s t . c l a s s p a t h " /> <p a t h e l e m e n t path=" $ { t e s t .c l a s s e s " /> 12 < !−− D i r e c t o r i o de b i b l i o t e c a s d e l p r o y e c t o −− > 13 <p r o p e r t y name=" l i b " l o c a t i o n=" . entre las l´ ıneas 15-18. / e x c e p c i o n e s " /> 4 < !−− D i r e c t o r i o de c l a s e s c o m p i l a d a s −− > 5 <p r o p e r t y name=" b u i l d . o al directorio destino de las clases compiladas de prueba y al directorio donde est´n todas las bibliotecas del proyecto respectivamente. Ejecuci´n de las Pruebas Unitarias o El Listado 10. c l a s s e s . c l a s s p a t h " /> <c l a s s p a t h </ j a v a c> 34 </ t a r g e t> 35 </ p r o j e c t> Listado 10.7 muestra c´mo ejecutar una bater´ de pruebas y grabar el reo ıa sultado a un fichero como un informe con formato de texto.

d i r } " /> 11 < j u n i t printsummary=" t r u e " 12 h a l t o n f a i l u r e=" f a l s e " 13 f a i l u r e p r o p e r t y=" t e s t . esta posibilidad es interesante ya que a partir de estos . t e s t s " 8 d e s c r i p t i o n=" E j e c u t a l o s t e s t s u n i t a r i o s "> 9 <mkdir d i r=" $ { r e p o r t s . donde se muestran s´lo las l´ o ıneas a˜adidas al fichero build.. Tambi´n se han u e a˜adido las propiedades y estructuras path-like necesarias para la ejecuci´n de n o las pruebas.x m l " depends=" c o m p i l e . x m l .t e s t s " depends=" c o m p i l e " d e s c r i p t i o n=" C o m p i l a l o s t e s t s . c l a s s " /> 19 </ f i l e s e t> 20 </ b a t c h t e s t> 21 </ j u n i t> 22 </ t a r g e t> Listado 10. t x t . adem´s estamos indicando que el formato ´ a de los informes sea xml. f a i l u r e s "> 14 <c l a s s p a t h r e f i d=" t e s t .xml. d i r } " /> 59 </ j u n i t> 60 </ t a r g e t> 61 </ p r o j e c t> Listado 10. d i r } " /> 52 < j u n i t printsummary=" t r u e " 53 h a l t o n f a i l u r e=" f a l s e " 54 f a i l u r e p r o p e r t y=" t e s t . c l a s s e s . d i r } " /> <j a v a c s r c d i r=" $ { t e s t . d i r " l o c a t i o n=" $ { r e p o r t s . d i r } "> 17 < f i l e s e t d i r=" $ { t e s t .7: Ejecutar la bater´ de pruebas unitarias. este es el objetivo que se invoca al ejecutar Ant. c l a s s p a t h " /> 56 <f o r m a t t e r t y p e=" p l a i n " /> 57 < t e s t name=" t e s t . o F´ ıjate. x m l .6. d i r } " /> <j a v a c s r c d i r=" \ $ { s r c . si no se selecciona ning´n otro. c l a s s e s . c l a s s e s . c l a s s p a t h " /> </ j a v a c> </ t a r g e t> <t a r g e t name=" t e s t " depends=" c o m p i l e .7 se ha a˜adido el atributo default="test" al proyecto n para indicar que el objetivo test es el objetivo por defecto. c o m p i l e .8: Ejecutar s´lo algunas de las pruebas. d i r } " /> 51 <mkdir d i r=" $ { r e p o r t s . d i r } / x m l " /> . ıa En el Listado 10. EJECUCION DE LAS PRUEBAS UNITARIAS 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 149 <mkdir d i r=" $ { b u i l d . <t a r g e t name=" t e s t . t x t . c l a s s e s . "> <mkdir d i r=" $ { t e s t . Si unicamente queremos ejecutar algunas de las pruebas y no toda ´ la suite utilizar´ ıamos la variante mostrada en el Listado 10. d i r } " /> 10 <mkdir d i r=" $ { r e p o r t s . d i r } "> 18 <i n c l u d e name=" * * / T e s t * .. A l l T e s t s " 58 t o d i r=" $ { r e p o r t s . n 1 2 3 4 5 6 7 < !−− D i r e c t o r i o p a r a l o s i n f o r m e s en f o r m a t o xml −− > <p r o p e r t y name=" r e p o r t s . d i r } " /> </ t a r g e t> <t a r g e t name=" c o m p i l e .´ 10. d i r } " d e s t d i r=" $ { t e s t .t e s t s " 49 d e s c r i p t i o n=" E j e c u t a l o s t e s t s u n i t a r i o s "> 50 <mkdir d i r=" $ { r e p o r t s . que en este ultimo caso. c l a s s p a t h " /> 15 <f o r m a t t e r t y p e=" x m l " /> 16 <b a t c h t e s t t o d i r=" $ { r e p o r t s . c l a s s e s . x m l . d i r } "> <c l a s s p a t h r e f i d=" t e s t . f a i l u r e s "> 55 <c l a s s p a t h r e f i d=" t e s t .8. d i r } " d e s t d i r=" $ { b u i l d .

Otros atributos e utiles son author. donde. o 1 2 3 4 5 6 7 < !−− D i r e c t o r i o p a r a l a d o c u m e n t a c i ´ n −− o > <p r o p e r t y name=" r e p o r t s .150 ´ CAP´ ITULO 10. Generaci´n de la documentaci´n o o Otra tarea que se puede automatizar es la generaci´n de la documentaci´n o o de nuestro proyecto tal y como muestra el Listado 10.7.. d i r } / h t m l " /> . d i r " l o c a t i o n=" $ { r e p o r t s .9. h t m l .1 " 14 w i n d o w t i t l e=" $ { a n t . p r o j e c t . si su valor es true se a˜adir´ informaci´n de la o n a o versi´n. j a v a d o c } " 11 a u t h o r=" t r u e " version=" t r u e " 12 u s e=" t r u e " a c c e s s=" p r i v a t e " 13 l i n k s o u r c e=" t r u e " e n c o d i n g=" ISO . n a m e } "> 15 <c l a s s p a t h> 16 <p a t h e l e m e n t path=" $ { t e s t . x m l " /> 12 </ f i l e s e t> 13 <r e p o r t f o r m a t=" f r a m e s " 14 t o d i r=" $ { r e p o r t s . y version. "> 9 <j a v a d o c s o u r c e p a t h=" $ { s r c . h t m l . <t a r g e t name=" j a v a d o c " depends=" c o m p i l e " 8 d e s c r i p t i o n=" G e n e r a l a d o c u m e n t a c i o ? n d e l p r o y e c t o .. CONSTRUCCION DE PROYECTOS CON ANT informes podremos hacer sobre ellos una transformaci´n para generarlos en foro mato html tal y como muestra el Listado 10. d i r } " /> 18 </ c l a s s p a t h> 19 </ j a v a d o c> 20 </ t a r g e t> Listado 10. La tarea <javadoc> tiene algunos atributos interesantes. se generar´ documentaci´n de todos a o los m´todos y atributos cuya visibilidad sea private o mayor. En nuestro ejemplo.8 8 5 9 .9: Generar informes de las pruebas en formato xml. x m l . d i r } " 10 d e s t d i r=" $ { r e p o r t s . s´lo aparecen o las l´ ıneas a˜adidas al fichero build.10.xml. x m l .. 10.* . <t a r g e t name=" t e s t . d i r } / j a v a d o c " /> . de nuevo. c l a s s e s . d i r } "> 10 < f i l e s e t d i r=" $ { r e p o r t s . r e p o r t s " depends=" t e s t " 8 d e s c r i p t i o n=" G e n e r a l o s i n f o r m e s d e l o s t e s t s e n f o r m a t o x m l "> 9 < j u n i t r e p o r t t o d i r=" $ { r e p o r t s . j a v a d o c " l o c a t i o n=" $ { r e p o r t s . d i r } " /> 15 </ j u n i t r e p o r t> 16 < f a i l i f =" t e s t . f a i l u r e s " 17 message=" S e h a n p r o d u c i d o e r r o r e s e n l o s t e s t s . c l a s s e s . d i r } "> 11 <i n c l u d e name=" T E S T . si su valor es true se a˜adir´ informaci´n del autor a la ´ n a o documentaci´n.10: Generaci´n de la documentaci´n del proyecto. o o . d i r } " /> 17 <p a t h e l e m e n t path=" $ { b u i l d . como por ejemplo access que nos permite indicar los m´todos y atributos de los que se generar´ la documentaci´n seg´n su e a o u modificador de acceso.. " /> 18 </ t a r g e t> Listado 10. n 1 2 3 4 5 6 7 < !−− D i r e c t o r i o p a r a l o s i n f o r m e s en f o r m a t o html −− > <p r o p e r t y name=" r e p o r t s .

EMPAQUETADO DE LA APLICACION 151 10. 1 2 <t a r g e t name=" c l e a n " d e s c r i p t i o n=" L i m p i a e l p r o y e c t o "> <d e l e t e d i r=" \ $ { d i s t .12: Ejecuci´n del proyecto como un fichero empaquetado. E indicar los ficheros que se van a incluir dentro del fichero empaquetado mediante una estructura path-like. d i r } / \ $ { d i s t . n a m e } "> 13 < f i l e s e t d i r=" $ { b u i l d . "> 4 <j a v a 5 j a r=" $ { d i s t .C l a s s " 17 v a l u e=" c o n v e r s o r .9. Tambi´n podemos borrar los directorios con las clases compiladas y los infore mes por si nos es de utilidad. tal y como se muestra en el Listado 10.13 muestra el objetivo clean formado por un conjunto de tareas <delete> que borran los directorios deseados. d i r } " /> .11: Empaquetado del proyecto. tal y como muestra el Listado 10. d i r } " /> 12 < j a r d e s t f i l e =" $ { d i s t . e o usando la tarea <java> de Ant. n a m e " v a l u e=" C o n v e r s o r T e m p e r a t u r a s .´ 10. n a m e } " 6 f o r k=" t r u e " /> 7 </ t a r g e t> 1 2 Listado 10. 10. Empaquetado de la aplicaci´n o Ant Tambi´n nos proporciona la tarea <jar> para empaquetar nuestra aplicae ci´n. P r i n c i p a l " /> 18 </ m a n i f e s t> 19 </ j a r> 20 </ t a r g e t> Listado 10. Podemos tambi´n indicar el contenido del e fichero de manifiesto con la etiqueta <manifest>. <t a r g e t name=" e x e c u t e " depends=" p a c k a g e " 3 d e s c r i p t i o n=" E j e c u t a l a a p l i c a c i o ? n . < !−− D i r e c t o r i o p a r a e l f i c h e r o empaquetado −− > <p r o p e r t y name=" d i s t .12. En este caso.8. d i r " l o c a t i o n=" d i s t " /> 3 < !−− Nombre d e l f i c h e r o empaquetado −− > 4 <p r o p e r t y name=" d i s t . como un fichero empaquetado. La sintaxis de la tarea es bastante autoexplicativa.11. j a r " /> 1 2 5 6 7 8 9 .. cosa que indicamos con el valor true del atributo a fork de la tarea java. Ejecuci´n y limpieza o Tambi´n podemos ejecutar nuestra aplicaci´n. d i r } / $ { d i s t . c l a s s e s . El Listado 10. <t a r g e t name=" p a c k a g e " depends=" c o m p i l e " 10 d e s c r i p t i o n=" G e n e r a e l f i c h e r o j a r " > 11 <mkdir d i r=" $ { d i s t . hemos empleado la o etiqueta <property> con el atributo <value> para definir el nombre del fichero empaquetado..8. d i r } " /> 14 <m a n i f e s t> 15 <a t t r i b u t e 16 name=" M a i n . hay que indicar el nombre del fichero empaquetado con el atributo destfile de la etiqueta jar. o Cabe destacar que para ejecutar la aplicaci´n se debe crear una nueva inso tancia de la m´quina virtual.

En el Ap´ndice A se muestra el listado completo del fichero build.apache. En espa˜ol. .org/ o manual/index.152 3 4 ´ CAP´ ITULO 10.html.13: Borrado de directorios. esta es la direcci´n directa http://ant.xml. e Lecturas recomendadas. d i r } " /> <d e l e t e d i r=" \ $ { r e p o r t s . El cap´ ıtulo 1 de la referencia [13] presenta la herramienta Ant de modo conciso pero muy informativo. Sin duda la referencia b´sica sobre Ant se encuentra el la propia p´gina a a web del proyecto. CONSTRUCCION DE PROYECTOS CON ANT <d e l e t e d i r=" \ $ { b u i l d . es interesante el cap´ n ıtulo 3 de la referencia [5]. d i r } " /> 5 </ t a r g e t> Listado 10.

11. . o 11. . . .5. .3. APIs para la programaci´n de interfaces gr´ficos o a de usuario en Java: AWT y Swing . . . . 11.5. listas de selecci´n .5. . .5. . JLabel.4. o Java proporciona dos grandes APIs para programar interfaces gr´ficas de a 153 . la interacci´n con nuestras aplicaciones ha sido a trav´s de consola. . . . . o 11. Gestores de Aspecto (Layout Managers) . . 11.1. las aplicaciones basadas en interfaces gr´ficos de usuario a son m´s intuitivas y la entrada de datos puede estar acotada. . . El patr´n de dise˜ o Modelo/Vista/Controlador . . . . . . . . .5. . . . . . . . . . .Cap´ ıtulo 11 Interfaces gr´ficas de a usuario Contenidos 11. .5. 11. .2. . . JCheckBox. . evitando que el a usuario introduzca valores err´neos. .5. 11. . . . o e los datos de entrada los tecleamos en consola.1. botones que el usuario puede pulsar . o Por contrapartida. . . . . Algunos componentes Swing . o n 154 155 155 157 162 162 162 163 164 166 166 168 . .6. JTextField. . . . . o u 11. Detecci´n de eventos: Escuchadores . . . . . . 11.3. . Contenedores y Componentes . . . . . . Introducci´n o Hasta ahora. .5. . . botones de opciones . .6. .4. . . . . JButton. . o 11. . JRadioButton. . . . . . muestra texto o iconos . JList. y la respuesta la obten´ ıamos tambi´n directamente en consola. . . botones de selecci´n m´ltiple . 11. .2. . . Uno de los principales inconvenientes de este tipo de interfaces de usuario es que son poco intuitivos y por lo tanto susceptibles de crear confusi´n en el usuario y como resultado que los datos de entrada al programa sean o err´neos. campos de introducci´n de texto . e Cada vez es menor el n´mero de aplicaciones con interfaces de usuario basau dos en consola. .

Swing ha ido desplazando a AWT en la creaci´n de interfaces o gr´ficos de usuario en Java. Por ejemplo. de modo que una clase s´lo puede formar parte bien del Moo delo. n e ´ o 11. existen dos APIs para la programaci´n de interfaces gr´ficos de usuario o a AWT (Abstract Window Toolkit) y Swing. Se tiene control absoluto sobre el aspecto de los componentes. y por otro lado no se pueden a introducir cambios en el aspecto de los componentes. Veremos con detalle este patr´n o de dise˜o y alguna t´cnica util para su implementaci´n. o a El Sistema Operativo se encarga de dibujar los componentes gr´ficos y de a la detecci´n de eventos. bien de la Vista o bien del Controlador. AWT fue la primera API disponible en Java y sus principales caracter´ ısticas son: La creaci´n de componentes gr´ficos se delega al Sistema Operativo. En este cap´ ıtulo veremos cuales son las caracter´ ısticas de ambas y justificaremos por qu´ elegir una sobre e otra. tales como botones y cajas de edici´n de texto. es el patr´n de dise˜o Modelo/Viso o n ta/Controlador. uno de ellos. a . El API Swing viene a liberar la creaci´n de interfaces gr´ficos de la carga o a que supone la dependencia con respecto al Sistema Operativo. Los interfaces gr´ficos de usuario son anteriores a la aparici´n del lenguaje a o de programaci´n Java. INTERFACES GRAFICAS DE USUARIO usuario: Abstract Windows Toolkit (AWT) y Swing. y ser´ tarea del programador escribir el c´digo necesario para a o escuchar el tipo de eventos que le interese y actuar en consecuencia cuando se produzca uno. Por todo ellos. ampliamente utilizado en otros lenguajes de n programaci´n como por ejemplo Smalltalk. Las principales caracter´ ısticas de este API son: Swing se encarga de dibujar los componentes y de detectar la interacci´n o sobre ellos. y en su programaci´n se han descubierto interesantes o o patrones de dise˜o. Este patr´n de dise˜o agrupa las clases de una aplicaci´n seg´n o n o u su responsabilidad. este lanza un evento o como respuesta. El conjunto de componentes es m´s grande que el que proporciona el a Sistema Operativo. La programaci´n de interfaces gr´ficos de usuario est´ basada en la idea de o a a que los componentes gr´ficos. de modo que la aplicaci´n se puede ralentizar o o si la interfaz contiene muchos elementos gr´ficos. cada vez que el usuario hace click sobre un bot´n. o El aspecto de la aplicaci´n es el nativo del Sistema Operativo.154 ´ CAP´ ITULO 11. APIs para la programaci´n de interfaces o gr´ficos de usuario en Java: AWT y Swing a En Java. a o son capaces de lazar eventos cuando el usuario interacciona sobre ellos. o La principal desventaja de AWT es que descansa directamente sobre el Sistema Operativo quien interviene tanto en la creaci´n de componentes gr´ficos o a como en la detecci´n de eventos.1.

o o Java nos facilita esta tarea mediante el uso de Gestores de Aspecto (Layout Managers en ingl´s).1 muestra un ejemplo de este comportamiento. a o 11. La Figura 11. de tal modo n n que si no hay espacio suficiente para insertar un nuevo Componente en la l´ ınea actual. y JPanel que no tiene un aspecto visual. La diferencia entre ellos es que los Contenedores pueden albergar otros Contenedores o Componentes dentro de ellos.2. y los Componentes son los elementos gr´ficos con los que el usuario puede interaccionar. Contenedores y Componentes Dentro de Swing tenemos dos grandes grupos de elementos: los Contenedores y los Componentes. e Los tres Contenedores que disponibles en Swing son JFrame que representa una ventana con marco. el Componente se a˜adir´ al n a principio de una nueva l´ ınea por debajo de la actual. BoxLayout coloca cada nuevo componente al la izquierda del ultimo ´ componente a˜adido. como en el sentido de la escritura del espa˜ol. Este Gestor de Aspecto es el que por defecto utiliza JPanel cada .1: Colocaci´n de Componentes con FlowLayout. por ejemplo. listas. CONTENEDORES Y COMPONENTES 155 Figura 11. porque se ha llegado al borde de la ventan.11. e La idea b´sica es que vamos a utilizar los JPanel como mu˜ecas rusas. o 11. as´ o ı.3. su cometido es albergar otros Contenedores o Componentes dentro de ´l. de a n modo que colocaremos Componentes dentro de JPanel y esos JPanel dentro de otros JPanel con m´s Componentes para ir creando el aspecto deseado para el a interfaz gr´fico de nuestra aplicaci´n. como por a ejemplo botones. etc´tera. Estos Gestores de Aspecto son los encargados de colocar e los Componentes que vamos a˜adiendo en los Contenedores. JWindow que representa una ventana sin marco. Gestores de Aspecto (Layout Managers) Cuando se programan interfaces gr´ficos de usuario. un aspecto importante es a la colocaci´n de los Componentes dentro de la ventana de nuestra aplicaci´n.2. Cada uno de los n Gestores de Aspecto sigue una pol´ ıtica de colocaci´n de los componentes.

add (new JButton ( " E s t e " ) . BorderLayout. JFrame . JButton . } private void creaGUI ( ) { JFrame v e n t a n a = new JFrame ( " B o r d e r L a y o u t M a n a g e r " ) . El c´digo fuente de este sencilla ejemplo aparece o en el Listado 11. v e n t a n a . awt . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package g u i . ventana . import j a v a x . c o n t e n e d o r . s w i n g .EAST. EAST) . BorderLayout .WEST) . add (new JButton ( " O e s t e " ) .NORTH. import j a v a x .CENTER. La a n o Figura 11. c o n t e n e d o r . S w i n g U t i l i t i e s . el nuevo componente ser´ a˜adido a la regi´n central. add (new JButton ( " N o r t e " ) . JFrame posee otro Gestor de n e Aspecto por defecto BorderLayout. Container contenedor = ventana . import j a v a . dentro de las cuales s´lo podeo mos a˜adir un Componente o Contenedor con el m´todo add(Component n e componente. 400) . o vez que a˜adimos sobre ´l un Componente. BorderLayout . s e t S i z e ( 4 0 0 .2: Colocaci´n de Componentes con BorderLayout.1.NORTH) . si no indicamos la zona (add(Component componente). add (new JButton ( " C e n t r o " ) ) . BorderLayout . c o n t e n e d o r . awt .WEST. public f i n a l c l a s s EjemploBorderLayout { private EjemploBorderLayout ( ) { super ( ) . i n v o k e L a t e r (new Runnable ( ) { @Override public void run ( ) { . s e t V i s i b l e ( true ) .2 muestra una ventana en la que se observa la disposici´n de las o cinco zonas de BorderLayout. BorderLayout . BorderLayout. c o n t e n e d o r . INTERFACES GRAFICAS DE USUARIO Figura 11. c o n t e n e d o r .SOUTH) . BorderLayout. import j a v a x . } public s t a t i c void main ( S t r i n g [ ] a r g s ) { S w i n g U t i l i t i e s . add (new JButton ( " S u r " ) . C o n t a i n e r . Este Gestor de Aspecto define 5 zonas BorderLayout.156 ´ CAP´ ITULO 11. s w i n g . s w i n g . getContentPane ( ) . import j a v a . BorderLayout.SOUTH. BorderLayout . int zona).

los pasos que debemos dar para responder cuando un evento ocurra son: 1 Este comportamiento es igualmente seguido en otros muchos lenguajes de programaci´n o . instancia de n o JButton a cada uno de las cinco regiones que define un BorderLayout. en la l´ n ınea 23 hacemos visible la ventana. En la l´ ınea 16. el componente informa al observador de que el evento ha ocurrido cada vez que este se produce. } }) . Detecci´n de eventos: Escuchadores o Si has probado a ejecutar el c´digo del Listado 11. o a No existe ning´n error en la aplicaci´n. simplemente. o o Para entender lo que est´ realmente ocurriendo tenemos que conocer de a qu´ modo act´an los Contenedores y Componentes en Java1 . En las l´ ınea 28-33 estamos utilizando un t´cnica e que quedar´ definitivamente clara cuando veamos c´mo programar hilos en Java a o en el Cap´ ıtulo 14. La secci´n 16.LayoutManager) al que se le pasa una instancia del nuevo Gestor de Aspecto que queremos utilizar. uno a la izquierda de otro. y cuando los recibe actuar en consecuencia. En la l´ ınea 22 estamos indicando el tama˜o de la ventana. estamos almacenando una referencia al contenedor de la ventana principal. que permite definir una rejilla con filas y columnas.1: Ejemplo de uso de BorderLayout El Listado 11. al cerrar la ventana. De nuevo nos encontramos con un patr´n de dise˜o o n llamado Observador. o o n La Figura 11. el programador escribe c´digo que observa cuando un evento ocurre. Por su lado.9 presenta este patr´n de dise˜o con detalle. pero con ello no su fuerza a que acabe la ejecuci´n de la aplicaci´n. el programador debe escuchar estos eventos. creaGUI ( ) . en este momento basta decir que en esas l´ ıneas de c´digo se o est´ creando un hilo para atender al interfaz gr´fico de usuario de modo que no a a interfiere con el hilo de la aplicaci´n principal.1 contiene algunos detalles importante. uno encima de otro.´ 11. que es donde a˜adimos los botones.4.1 quiz´s te hayas dado cuenta o a del siguiente detalle. Las l´ n ıneas 17-21 a˜aden un bot´n. 11. la ventana se cierra pero la aplicaci´n sigue ejecut´ndose. } } Listado 11. o Los Gestores de Aspecto por defecto se pueden cambiar con el m´todo e setLayout(java. e u La idea b´sica es que cuando el usuario interacciona con los Contenedores a o los Componentes estos lanzan eventos como respuesta. DETECCION DE EVENTOS: ESCUCHADORES 31 32 33 34 35 157 new EjemploBorderLayout ( ) .3 muestra gr´ficamente la din´mica en la detecci´n de eventos. Otros Gestores de Aspecto son GridLayout.4. o y le indica al componente que quiere ser informado cuando el evento ocurra. al pulsar sobre el bot´n de cerrar la ventana que aparece o en el marco de esta. lo que u o en realidad est´ ocurriendo es que se hace invisible. a a o De modo resumido. u horizontalmente. y BoxLayout nos permite disponer los componentes verticalmente. y podemos a˜adir un componente dentro de cada una n de las posiciones dentro de la rejilla. Dicho de otro modo. y finalmente.awt.

com/docs/cd/E17409_01/javase/ a tutorial/uiswing/events/eventsandcomponents. Conocer cual es el tipo de eventos genera el Contenedor o Componente que nos interesa. 2. para ello podemos cono sultar la p´gina http://download.158 ´ CAP´ ITULO 11. el interface capaz de escucharlo se llamar´ xxxListener a 3 F´ ıjate de nueva en la nomenclatura utilizada para nombrar el m´todo que a˜ ade el escue n chador al Contenedor. si el escuchador es xxxListener. e La Figura 11. INTERFACES GRAFICAS DE USUARIO Figura 11. a o Figura 11. supongamos que deseamos cerrar la aplicaci´n cuando el usuario hao o ga click sobre el bot´n de cierre de la ventana. donde encontramos que JFrame lanza eventos de tipo WindowEvent. el m´todo que lo a˜ade al Contenedor e n o Componente es addxxxListener(interface xxxListener) .html.4 muestra la din´mica en la detecci´n de eventos generados por a o JFrame. 2 Observa la nomenclatura usada en el nombrado de eventos y sus correspondientes escuchadores: si encontramos un evento de tipo xxxEvent. Finalmente a˜adiremos una instancia de la clase que implementa el n interface WindowListener como escuchador a la ventana.1.oracle. Para ver de modo detallado como los pasos anteriores se concretan en c´digo. Si lo unico que queremos hacer es cerrar la aplicaci´n ´ o cuando el usuario cierra la ventana. cuando el e usuario hace click sobre el bot´n correspondiente. A esta clase la llamaremos clase escuchadora. con el m´todo e addWindowListener3 . A˜adir una instancia de la clase escuchadora a la lista de observadores del n Contenedor o el Componente. que es nuestra ventana. En la anterior direcci´n web encontramos que es WindowListener2 . 3.3: Din´mica de la detecci´n de eventos en Swing. el unico m´todo al que a˜adiremos c´digo ´ e n o es public void windowClosing(WindowEvent e). El siguiente paso es conocer cual es el interface capaz de escuchar este tipo de eventos. La clase que implemente este interface debe definir cada uno de los m´toe dos de la Tabla 11. 1.4: Din´mica de la detecci´n de eventos para el caso particular de a o WindowEvent. o Este interface declara m´todos cuyo significado aparece en la Tabla 11. Conocer cual es el interface capaz de escuchar a ese tipo de eventos y escribir una clase que lo implemente. El primer paso es conoo cer qu´ tipo de eventos lanza JFrame.1.

Se invoca cuando la ventana se minimiza. } }) . Se invoca cuando la ventana pasa de estar minimizada a tener su estado normal. i n v o k e L a t e r (new Runnable ( ) { @Override public void run ( ) { new EjemploWindowListener ( ) . awt . WindowListener . S w i n g U t i l i t i e s . El Listado 11. } public s t a t i c void main ( S t r i n g [ ] a r g s ) { S w i n g U t i l i t i e s . } private void creaGUI ( ) { // Creamos l a v e n t a n a JFrame v e n t a n a = new JFrame ( " A p l i c a c i ´ n q u e s e c i e r r a c o n l a v e n t a n . WindowEvent . Tabla 11. e v e n t . DETECCION DE EVENTOS: ESCUCHADORES windowOpened(WindowEvent e) windowClosing(WindowEvent e) windowClosed(WindowEvent e) windowIconified(WindowEvent e) windowDeiconified(WindowEvent e) 159 windowActivated(WindowEvent e) windowDeactivated(WindowEvent e) Se invoca cuando la ventana se abre. v e n t a n a . import j a v a x . addWindowListener ( t h i s ) . s w i n g .4. s w i n g . JFrame . ventana . import j a v a .2 muestra un ejemplo completo de un escuchador para los eventos de la ventana que cierra la aplicaci´n cuando el usuario pulsa el bot´n o o de cerrar ventana. Se invoca cuando se intenta cerrar la ventana. e v e n t . awt . " ) o . s e t V i s i b l e ( true ) . import j a v a . 400) . import j a v a x .´ 11. s e t S i z e ( 4 0 0 . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 package g u i . // Esta c l a s e implementa WindowListener l u e g o e s e s c u c h a d o r de WindowEvent public c l a s s EjemploWindowListener implements WindowListener { private EjemploWindowListener ( ) { super ( ) . // A˜ adimos como e s c u c h a d o r l a i n s t a n c i a de e s t a c l a s e n v e n t a n a . Se invoca cuando la ventana se ha cerrado definitivamente. Se invoca cuando la ventana deja de ser la ventana activa. creaGUI ( ) .1: M´todos declarados en la interface WindowListener todos ellos e son public void. } // Los m´ todos que s i g u e n e s t a n d e c l a r a d o s en l a e ´ WindowListener @Override public void windowOpened ( WindowEvent e ) { } interface . Se invoca cuando la ventana pasa a ser la ventana activa.

miento es el mismo que el ejemplo del Listado 11. " ) . es o e a decir. o u t . que implementa la interface definiendo todos los m´todos vac´ ¿Cual es la ventaja de utilizar estas clases adaptadoras?.2: Aplicaci´n que finaliza cuando se cierra la ventana. Si el Listado 11. la implementao e ci´n del resto de m´todos ser´ la que nos proporcione la clase adaptadora. s w i n g . . System . awt . . WindowEvent . S w i n g U t i l i t i e s . pues que nuestros escuchadores en vez de implementar el interface extienden la clase adaptadora. awt . s w i n g . Java nos proporciona un clase de o o conveniencia. ya que hemos tenido que definir todos los m´todos dej´ndolos vac´ e a ıos excepto el m´todo e windowClosing(WindowEvent e). WindowAdapter . ser´n todos vac´ El Listado 11. // A˜ adimos como e s c u c h a d o r una i n s t a n c i a de una c l a s e i n t e r n a an´ nima n o // que e x t i e n d e a WindowAdapter y s ´ l o s o b r e s c r i b e e l m´ todo o e windowClosing . public f i n a l c l a s s E j e m p l o C l a s e A d a p t a d o r a { private E j e m p l o C l a s e A d a p t a d o r a ( ) { super ( ) . import j a v a . e x i t ( 0 ) . } @Override public void windowClosed ( WindowEvent e ) { } @Override public void w i n d o w I c o n i f i e d ( WindowEvent e ) { } @Override public void w i n d o w D e i c o n i f i e d ( WindowEvent e ) { } @Override public void wi ndowA cti vate d ( WindowEvent e ) { } @Override public void w i n d o w D e a c t i v a t e d ( WindowEvent e ) { } } Listado 11. o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package g u i .2 te ha parecido tedioso. import j a v a . .3 muestra un ejemplo cuyo comportaa ıos. y s´lo sobrescriben los m´todos necesarios. En los casos en los o que una interface tiene declarados muchos m´todos. llamada adaptadora.2. tu sensaci´n es acertada. JFrame . } private void creaGUI ( ) { // Creamos l a v e n t a n a JFrame v e n t a n a = new JFrame ( " E s c u c h a d o r c o n c l a s e a d a p t a d o r a . " ) . La clase o principal implementa el interface WindowListener.160 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 ´ CAP´ ITULO 11. import j a v a x . e v e n t . import j a v a x . e ıos. e v e n t . por lo que se puede a˜adir n como escuchador de eventos WindowEvent. de los que usualmente e s´lo se escribe c´digo para algunos de ellos. pero utilizando una clase interna an´nima que extiende la clase adaptadora WindowAdapter. INTERFACES GRAFICAS DE USUARIO // E s t e e s e l u n i c o m´ todo con c o d i g o ´ e ´ @Override public void w i n d o w C l o s i n g ( WindowEvent e ) { System . p r i n t l n ( " C e r r a n d o l a v e n t a n a .

y registrando esa clase como escuchador del Contenedor o Componente. El Listado 11. ventana . creaGUI ( ) . } } Listado 11. public c l a s s E j e m p l o S e t D e f a u l t C l o s e O p e r a t i o n { private E j e m p l o S e t D e f a u l t C l o s e O p e r a t i o n ( ) { super ( ) . s w i n g .3: Uso de la clase adaptadora WindowAdapter para cerrar la aplicaci´n al cerrar la ventana. import j a v a x . e 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package g u i . DETECCION DE EVENTOS: ESCUCHADORES 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 161 v e n t a n a . // Usamos e l m´ todo de c o n v e n i e n c i a s e t D e f a u l t C l o s e O p e r a t i o n e v e n t a n a . } public s t a t i c void main ( S t r i n g [ ] a r g s ) { S w i n g U t i l i t i e s . En la secci´n siguiente vamos a ver algunos de los Componentes Swing m´s o a .4 muestra un ejemplo de uso de este m´todo. } }) . s e t V i s i b l e ( true ) . s e t V i s i b l e ( true ) . i n v o k e L a t e r (new Runnable ( ) { @Override public void run ( ) { new E j e m p l o C l a s e A d a p t a d o r a ( ) . " ) . } public s t a t i c void main ( S t r i n g [ ] a r g s ) { S w i n g U t i l i t i e s . 400) . este m´todo es o e setDefaultCloseOperation(int modo). 400) . } private void creaGUI ( ) { // Creamos l a v e n t a n a JFrame v e n t a n a = new JFrame ( " E s c u c h a d o r c o n c l a s e a d a p t a d o r a . la propia clases JFrame nos ofrece un m´todo para definir el e comportamiento de la aplicaci´n cuando se cierra la ventana. v e n t a n a . i n v o k e L a t e r (new Runnable ( ) { @Override public void run ( ) { new E j e m p l o S e t D e f a u l t C l o s e O p e r a t i o n ( ) .4. v e n t a n a . EXIT ON CLOSE) . ventana . s e t S i z e ( 4 0 0 . o Esta t´cnica de escucha de eventos es transversal a todos los Contenedores e y Componentes que forman parte de Swing. s w i n g .´ 11. JFrame . s e t S i z e ( 4 0 0 . } } Listado 11. } }) . } }) . import j a v a x . addWindowListener (new WindowAdapter ( ) { @Override public void w i n d o w C l o s i n g ( WindowEvent e ) { System . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . Los Contenedores y Componentes lanzan eventos que seremos capaces de escuchar implementando el interface adecuado en una clase. e x i t ( 0 ) . S w i n g U t i l i t i e s .4: Uso del m´todo setDefaultCloseOperation(int) para acabar la e aplicaci´n cuando se cierra la ventana. creaGUI ( ) . o Por otro lado.

import j a v a . a n 1 2 3 4 5 6 7 8 9 10 11 12 13 14 package g u i . pero s´ el ı programador. si queremos escuchar este tipo de evento. JButton . este m´todo calcula el tama˜o ´ptimo de la ventana para contener e n o todos los componentes que se le han a˜adido. este lanza un evento de tipo ActionEvent. import import import import import javax javax javax javax javax . swing . Otro detalle interesante es que hemos utilizado un JPanel para a˜adir sobre ´l los componentes JLabel y JButton y aprovechar que el n e Gestor de Aspecto de un JPanel es FlowLayout y coloca los Componentes en el sentido de la escritura. Finalmente.162 ´ CAP´ ITULO 11. . A c t i o n L i s t e n e r .5 muestra un ejemplo de detecci´n de los eventos ActionEvent. de este modo estamos delegando n en Swing el c´lculo del tama˜o de la ventana. .5. como hemos dicho. nos sirve para mostrar e texto o iconos. e v e n t . Cada vez que el usuario pulsa un JButton.1. swing . en las l´ ıneas 22-27 a˜adimos al bot´n un escuchador n o como una clase interna an´nima que implementa el interface ActionListener o y definimos el m´todo que declara esta interfaz public void actionPerformed e (ActionEvent e). no puede interaccionar sobre ´l.5. El Listado 11. 11. JLabel . ya que el usuau rio. public c l a s s EjemploJButton { private EjemploJButton ( ) { super ( ) . necesitamos implementar la interface ActionListener que unicamente declara un ´ m´todo public void actionPerformed(ActionEvent e) que ser´ invocado e a cada vez que el usuario pulse el bot´n. Este componente no lanza ning´n tipo de evento. INTERFACES GRAFICAS DE USUARIO comunes y se mostrar´n ejemplos de c´mo escuchar los eventos que se producen a o cuando el usuario interacciona sobre ellos. JButton. e v e n t . swing . botones que el usuario puede pulsar El siguiente componente en la lista es JButton con el que podemos crear botones que el usuario puede pulsar. JFrame . o o si no una muestra de c´mo utilizar la t´cnica que se ha mostrado en la secci´n o e o anterior para escuchar los eventos que producen. Algunos componentes Swing Esta secci´n no pretende ser una presentaci´n exhaustiva de Componentes Swing. awt . muestra texto o iconos El primer y m´s sencillo Componente Swing es JLabel que se muestra como a una cadena de texto o un icono que el usuario no puede modificar. s w i n g . o donde tambi´n se ha incluido un JLabel.2. En la l´ e ınea 21 creamos el bot´n como o una instancia de JButton. . import j a v a . Otro detalle nuevo es el uso del m´todo public void e pack(). S w i n g U t i l i t i e s . 11. registraremos el escuchador o al bot´n con el m´todo addActionListener(ActionListener escuchador) de o e la clase JButton. JPanel . . A c t i o n E v e n t .5. 11. JLabel. s w i n g . . awt .

. El Listado 11. pack ( ) . private E j e m p l o J T e x t F i e l d ( ) { super ( ) . javax javax javax javax public c l a s s E j e m p l o J T e x t F i e l d { private J T e x t F i e l d j t f T e x t o . awt . S w i n g U t i l i t i e s . c o n t e n e d o r . } }) . Este es el mismo evento o que lanza un bot´n cuando el usuario lo pulsa. JTextField . add ( c o n t e n e d o r ) . En la l´ ınea 29 hemos utilizado el m´todo String getText() e para obtener el texto introducido por el usuario en el JTextField.6 muestra un ejemplo de uso de JTextField. add ( jbBoton ) . EXIT ON CLOSE) . v e n t a n a . a d d A c t i o n L i s t e n e r (new A c t i o n L i s t e n e r ( ) { @Override public void a c t i o n P e r f o r m e d ( A c t i o n E v e n t e ) { System . En el momento de la instanciaci´n de o JTextField podemos indicar el n´mero de columnas. } . u Un JTextField lanza eventos de tipo ActionEvent cada vez que el usuario pulsa el bot´n Enter y este componente tiene el foco. p r i n t l n ( " B o t o n p u l s a d o " ) . A c t i o n L i s t e n e r . e v e n t . swing . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package g u i . v e n t a n a . awt . i n v o k e L a t e r (new Runnable ( ) { @Override public void run ( ) { new EjemploJButton ( ) . add (new J L a b e l ( " P u l s a e l b o t ´ n : " ) ) . e v e n t . FlowLayout . ´ } }) . s w i n g . . c o n t e n e d o r . swing . J P a n e l c o n t e n e d o r = new J P a n e l ( ) . swing . JFrame . luego el procedimiento para o escuchar los eventos es el mismo que en el caso de JButton.3. JTextField. v e n t a n a . awt . o JButton jbBoton = new JButton ( " P ´ l s a m e " ) .11. s e t V i s i b l e ( true ) . o u t .5. C o n t a i n e r . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . . awt . . F´ ıjate que esta vez en la l´ ınea 22 hemos optado por cambiar el Gestor de Aspecto del JFrame es vez de utilizar un JPanel intermedio. g e t C o n t e n t P a n e ( ) . } } Listado 11. u jbBoton . creaGUI ( ) . . ALGUNOS COMPONENTES SWING 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 163 } private void creaGUI ( ) { JFrame v e n t a n a = new JFrame ( " U n J L a b e l y u n J B u t t o n " ) .5: Ejemplo de uso de JButton 11. . import import import import import import import import java java java java .5. } public s t a t i c void main ( S t r i n g [ ] a r g s ) { S w i n g U t i l i t i e s . A c t i o n E v e n t . JLabel . v e n t a n a . . campos de introducci´n de texto o La clase JTextField dibuja una caja de edici´n de texto de una unica l´ o ´ ınea donde el usuario puede introducir texto.

pack ( ) . como en el caso anterior. } } Listado 11.SELECTED si lo que ha ocurrido es una selecci´n. v e n t a n a . j t f T e x t o . El evento ItemEvent nos da m´s a informaci´n sobre lo que ha ocurrido que ActionEvent. g e t T e x t ( ) ) .6: Ejemplo de uso de JTextField 11. o a o ItemEvent. nuestro conocido ActionEvent y el nuevo ItemEvent. add (new J L a b e l ( " I n t r o d u c e u n t e x t o : " ) ) . botones de opciones El siguiente Componente en complejidad es el bot´n de radio JRadioButton que o dibuja un bot´n asociado a una opci´n. Container contenedor = ventana . JRadioButton puede lanzar dos tipos de eventos interesante. y que este interface s´lo declara un m´todo public void actionPerformed(ActionEvent e) que o e se invoca cada vez que el bot´n se pulsa. a d d A c t i o n L i s t e n e r (new A c t i o n L i s t e n e r ( ) { @Override public void a c t i o n P e r f o r m e d ( A c t i o n E v e n t e ) { System . i n v o k e L a t e r (new Runnable ( ) { @Override public void run ( ) { new E j e m p l o J T e x t F i e l d ( ) . } }) . ya que nos dice si lo o que ha ocurrido es una selecci´n o una des-selecci´n del bot´n. o u t . v e n t a n a . JRadioButton. v e n t a n a . v e n t a n a . como por ejemplo para elegir la forma o o de pago Tarjeta/Transferencia/Cheque. v e n t a n a . p r i n t l n ( " E l t e x t o e s c r i t o e s : " + j t f T e x t o . EXIT ON CLOSE) . o . getContentPane ( ) . Para conocer si lo que ha ocurrido es una selecci´n o una de-selecci´n. Muchas veces las opciones presentadas al usuario son excluyentes. j t f T e x t o = new J T e x t F i e l d ( 5 0 ) . } public s t a t i c void main ( S t r i n g [ ] a r g s ) { S w i n g U t i l i t i e s .5.164 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 ´ CAP´ ITULO 11. s e t V i s i b l e ( true ) . } }) .DESELECTED si lo que ha ocurrido es una de-selecci´n. Este interface s´lo declao ra un m´todo public void itemStateChanged(ItemEvent e) que se invoe ca cada vez que el usuario selecciona o des-selecciona un JRadioButton. o o o Ya sabemos que los eventos de tipo ActionEvent los podemos escuchar con una clase que implemente el interface ActionListener a˜adida al Componente que queremos escuchar con el m´todo n e addActionListener(ActionListener escuchador). creaGUI ( ) . de modo que seleccionar una de ellas implica que se de-selecciona la anterior si hubiese alguna. add ( j t f T e x t o ) . c o n t e n e d o r . INTERFACES GRAFICAS DE USUARIO public void creaGUI ( ) { JFrame v e n t a n a = new JFrame ( ) . poo o demos utilizar el m´todo getStateChange() de la clase ItemEvent que nos e devolver´ ItemEvent.4. o En el caso de un evento de tipo ItemEvent lo podemos escuchar con una clase que implemente el interface ItemListener siempre que a˜adamos la instancia al Componente que queremos escuchar con n addItemListener(ItemListener escuchador). s e t L a y o u t (new FlowLayout ( ) ) . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame .

s w i n g . grupo . g e t S t a t e C h a n g e ( ) == ItemEvent . . BorderLayout . a d d A c t i o n L i s t e n e r ( e s c u c h a d o r ) . A c t i o n L i s t e n e r . o u t . JFrame . add ( j r b P o c o ) . . JRadioButton jrbMucho = new JRadioButton ( " M u c h o " ) . f o r m a t ( " B o t ´ n %s s e l e c c i o n a d o . } @Override public void a c t i o n P e r f o r m e d ( A c t i o n E v e n t e ) { System . a d d I t e m L i s t e n e r ( e s c u c h a d o r ) . e v e n t . JRadioButton j r b N o r m a l = new JRadioButton ( " N o r m a l " ) . \ n " . awt . awt . BorderLayout . addItemListener ( escuchador ) . e v e n t . BoxLayout . JRadioButton . c o n t e n e d o r . g e t T e x t ( ) . c o n t e n e d o r . } private c l a s s E s c u c h a d o r implements A c t i o n L i s t e n e r . s w i n g . pack ( ) . awt . EAST) . o e l s e i f ( e . EAST) . } private J P a n e l c r e a C o n t e n e d o r ( S t r i n g p o s i c i o n ) { J P a n e l c o n t e n e d o r = new J P a n e l ( ) . add ( j r b P o c o ) . ButtonGroup . c o n t e n e d o r . EAST) { ButtonGroup grupo = new ButtonGroup ( ) . g e t S o u r c e ( ) ) . jrbNormal .11. } return c o n t e n e d o r . o u t . . S w i n g U t i l i t i e s . I t e m L i s t e n e r . ALGUNOS COMPONENTES SWING 165 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 package g u i . \ n " . add ( j r b N o r m a l ) . . BorderLayout . BoxLayout . . t e x t o ) . v e n t a n a . add ( c r e a C o n t e n e d o r ( BorderLayout . o u t . v e n t a n a . . jrbPoco . . jrbPoco . grupo . g e t S t a t e C h a n g e ( ) == ItemEvent . public E s c u c h a d o r ( ) { super ( ) .5. EXIT ON CLOSE) . addItemListener ( escuchador ) .WEST) . s w i n g . c o n t e n e d o r . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . . jrbMucho . . o } @Override public void i t e m S t a t e C h a n g e d ( ItemEvent e ) { S t r i n g t e x t o = ( ( JRadioButton ) e . i f ( e . ItemEvent . o } } ItemListener { . v e n t a n a . s e t V i s i b l e ( true ) . awt . i f ( p o s i c i o n == BorderLayout . a d d A c t i o n L i s t e n e r ( escuchador ) . JRadioButton j r b P o c o = new JRadioButton ( " P o c o " ) . jrbNormal . A c t i o n E v e n t . } private void creaGUI ( ) { JFrame v e n t a n a = new JFrame ( " E j e m p l o J R a d i o B u t t o n " ) . import import import import import import import import import import import java java java java java . t e x t o ) . E s c u c h a d o r e s c u c h a d o r = new E s c u c h a d o r ( ) . . add ( c r e a C o n t e n e d o r ( BorderLayout . swing . add ( jrbMucho ) . p r i n t l n ( " B o t ´ n p u l s a d o " ) . jrbMucho . v e n t a n a . v e n t a n a . addActionListener ( escuchador ) . Y AXIS ) ) . s w i n g . e v e n t . SELECTED) System .DESELECTED) System . s e t L a y o u t (new BoxLayout ( c o n t e n e d o r . swing . e v e n t . JPanel .WEST) . f o r m a t ( " B o t ´ n %s d e s e l e c c i o n a d o . grupo . javax javax javax javax javax javax public f i n a l c l a s s EjemploJRadioButton { private EjemploJRadioButton ( ) { super ( ) . add ( j r b N o r m a l ) . add ( jrbMucho ) . awt .

creaGUI ( ) . y no tiene ninguna representaci´n gr´fica. o es la acci´n final.4 sobre los JRadioButton es v´lido para los o a JCheckBox. } }) .166 74 75 76 77 78 79 80 81 82 83 84 ´ CAP´ ITULO 11. es decir eventos ActionEvent y eventos ItemEvent para indicar. Adem´s a de lo ya comentado. o o o cuando el usuario suelta el bot´n del rat´n. Los JCheckBox lanzan los mismos tipos de eventos que los JRadioButton. 11.5. botones de selecci´n m´ ltiple o u Usualmente los botones de tipo JRadioButton se utilizan cuando las opciones presentadas al usuario son mutuamente excluyentes entre s´ y se han a˜adido a ı. Este evento nos indica si la selecci´n se est´ efectuano a do (por ejemplo. si hay alg´n otro bot´n u o previamente seleccionado este ultimo se des-seleccionar´.6.7: Ejemplo de uso de JRadioButton El Listado 11. INTERFACES GRAFICAS DE USUARIO public s t a t i c void main ( S t r i n g [ ] a r g s ) { S w i n g U t i l i t i e s . estos ultimos. se desplaza sobre los elementos de la lista). Si lo que queremos presentar al usuario son opciones no excluyentes solemos utilizar botones de tipo JCheckBox. JList. El usuario puede seleccionar una o m´s opciones dependiendo del modo de selecci´n de la a o lista. listas de selecci´n o La clase JList presentan al usuario varias opciones en forma de lista. 11. sin soltar el bot´n del rat´n. Los eventos que un JList puede lazar cada vez que el usuario selecciona una opci´n de la lista son nuestro conocido ActionEvent y el nuevo o ListSelectionEvent. Para consultar si . f´ ıjate que en las l´ ıneas 38-41 estamos utilizando una nueva clase ButtonGroup. Estos botones se dibujan como una peque˜a caja que al seleccionarlo aparece n marcada con un tick. La clase ButtonGroup ´ a crea un grupo l´gico. en la l´ ınea 23 hemos utilizado un nuevo Gestor de Aspecto. En la l´ o o a ınea 67 puedes ver como hemos recuperado el texto escrito a la derecha de cada uno de los JRadioButton. Por lo tanto todo o o lo comentado en la secci´n 11. el usuario pulsa sobre un elemento de la lista y. BoxLayout que nos permite disponer los Componentes verticalmente dentro de la ventana. n un ButtonGroup para comportarse de este modo. i n v o k e L a t e r (new Runnable ( ) { @Override public void run ( ) { new EjemploJRadioButton ( ) . JCheckBox. esta clase agrupa los botones de manera excluyente. de modo que cuando alguno de los botones se selecciona. ´ si lo que ha ocurrido es una selecci´n o una de-selecci´n. } } Listado 11.7 muestra un ejemplo con este nuevo Componente.5.5. o o Para escuchar los eventos de tipo ItemSelectionEvent debemos implementar la interface ItemSelectionListener que declara un unico m´to´ e do public void valueChanged(ListSelectionEvent e). Y finalmente.5.

event . " Sabado " . EXIT ON CLOSE) . g e t V a l u e I s A d j u s t i n g ( ) == f a l s e ) System . " Viernes " . a d d L i s t S e l e c t i o n L i s t e n e r (new E s c u c h a d o r ( ) ) .8: Ejemplo de uso de JList . . creaGUI ( ) . . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 package g u i . JFrame . .SINGLE SELECTION. o p c i o n e s . swing . o u t . swing .11. SINGLE SELECTION) . s w i n g . El Listado 11. getContentPane ( ) . v e n t a n a . C o n t a i n e r .5. swing . swing .8 muestra un ejemplo de uso de este componente. J L i s t o p c i o n e s = new J L i s t (new S t r i n g [ ] { " L u n e s " . e l s e i f ( e . awt . Container contenedor = ventana . L i s t S e l e c t i o n L i s t e n e r . o u t . J S c r o l l P a n e s c r o l l = new J S c r o l l P a n e ( o p c i o n e s ) . g e t V a l u e I s A d j u s t i n g ( ) == true ) System . getSelectedValue () ) . import j a v a . . g e t S o u r c e ( ) ) . swing . } } Listado 11. p r i n t l n ( " I t e m e n c u r s o : " + ( ( J L i s t ) e . s e t S e l e c t i o n M o d e ( L i s t S e l e c t i o n M o d e l . . import import import import import import import javax javax javax javax javax javax javax . i n v o k e L a t e r (new Runnable ( ) { @Override public void run ( ) { new E j e m p l o J L i s t ( ) . } } public s t a t i c void main ( S t r i n g [ ] a r g s ) { S w i n g U t i l i t i e s . c o n t e n e d o r . } private void creaGUI ( ) { JFrame v e n t a n a = new JFrame ( " E j e m p l o J L i s t " ) . v e n t a n a . add ( s c r o l l ) . " M i e r c o l e s " ´ . . " Jueves " . p r i n t l n ( " I t e m d e f i n i t i v o : " + ( ( J L i s t ) e . " Domingo " }) . pack ( ) . L i s t S e l e c t i o n E v e n t . o p c i o n e s . " M a r t e s " . setVisibleRowCount (5) . S w i n g U t i l i t i e s . J S c r o l l P a n e . Otros detalles interesantes de este ejemplo son el uso del m´todo setVisibleRowCount(int) e de la l´ ınea 25 para indicar cuantos elementos son visibles en la lista. v e n t a n a . event . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . swing . } private c l a s s E s c u c h a d o r implements L i s t S e l e c t i o n L i s t e n e r { @Override public void valueChanged ( L i s t S e l e c t i o n E v e n t e ) { i f ( e . J L i s t . public f i n a l c l a s s E j e m p l o J L i s t { private E j e m p l o J L i s t ( ) { super ( ) . ´ opciones . s e t V i s i b l e ( true ) . de modo que s´lo se podr´ seleccionar un elemento unico de la lista (otros modos posible son a ´ SINGLE INTERVAL SELECTION y MULTIPLE INTERVAL SELECTION). ALGUNOS COMPONENTES SWING 167 la selecci´n est´ en marcha o es definitiva podemos usar el m´todo o a e getValueIsAdjusting() de la clase ItemSelectionEvent. En la l´ ınea 23 activamos el modo de selecci´n de los elementos de o o la lista a ListSelectionModel. getSelectedValue () ) . L i s t S e l e c t i o n M o d e l . } }) . g e t S o u r c e ( ) ) .

INTERFACES GRAFICAS DE USUARIO Por defecto. La Vista informa al Controlador de lo ocurrido. . o debe leer los datos de la hipoteca y envi´rselos al Modelo para que este haga el a c´lculo. Veamos . el Componente JList no tiene una barra de desplazamiento para poder visualizar los elementos de la lista.6. El usuario interacciona sobre la Vista. o Vista es la responsable del interfaz gr´fico de usuario y la detecci´n de eventos a o sobre los componentes. el papel de cada uno de estos actores. o o n Este patr´n de dise˜o define tres actores con las siguientes responsabilidades: o n Modelo es el responsable de mantener y gestionar los datos de la aplicaci´n. y cuando pulsa el bot´n Calcula a o o aparece la nueva cuota en la parte inferior de la ventana. con un ejemplo. El usuario puede introducir los tres datos que se necesita para el c´lculo en tres cajas de edici´n de texto. lo tenemos que a˜adir tal y como se muestra en las l´ n ıneas 25 y 26. que se a o n detalla en los siguiente pasos: 1. a En la Figura 11. La Vista o e e es la encargada de crear el interfaz gr´fico y la detecci´n de los eventos sobre a o el interfaz. el Modelo contiene los datos de la hipoteca: cantidad hipotecada. duraci´n de la hipoteca.5 se muestra el interfaz gr´fico de una aplicaci´n que calcula la cuota mensual a o de una hipoteca. o u Con el componente JList acabamos la breve muestra de las posibilidades de creaci´n de interfaces gr´ficos de usuario Swing.6 se muestra la din´mica de este patr´n de dise˜o. o lo que pretende mostrar es la t´cnica de c´mo programar interfaces gr´ficos de e o a usuario con el patr´n de dise˜o Observable. F´ ıjate que indicamos el Componente al que asociaremos la barra de desplazamiento en el momento de crear esta. Esta secci´n no pretende ser o a o un exposici´n exhaustiva de todas las posibilidades que nos proporciona Swing. El Controlador sabe que cuando el usuario pulsa el bot´n Calcula. si la lista es de selecci´n unica. Controlador es quien hace corresponder la interacci´n del usuario con posible o cambios en el Modelo. En este caso. si queremos que la lista posea uno. El patr´n de dise˜ o Modelo/Vista/Cono n trolador Quiz´s el patr´n de dise˜o Modelo/Vista/Controlador sea uno de los m´s utilia o n a zados en el desarrollo de proyectos inform´ticos. Otros m´todos interesantes del Componente JList son Object e getSelectedValue() el elementos actualmente seleccionado. y Object [] getSelectedValues() si se lista es de o ´ selecci´n m´ltiple. inter´s del pr´stamo y la cuota mensual. Finalmente a˜adimos la barra de desplazamiento a n la ventana y no la lista original.168 ´ CAP´ ITULO 11. 2. o n 11. En la Figura 11. tanto es as´ que incluso existe a ı una adaptaci´n al mundo de aplicaciones web de este patr´n de dise˜o.

´ ˜ 11.5: Un interfaz gr´fico para el c´lculo de la cuota mensual de una a a hipoteca.6: Din´mica del modelo MVC. 6. e En el ejemplo del c´lculo de la cuota mensual de una hipoteca esta din´mica a a se concretar´ del siguiente modo: ıa 1. El Modelo calcula la nueva cuota e informa de ello a la Vista 6. El Controlador actualiza el Modelo. 3. El Modelo informa a la Vista de que se ha actualizado. a 3. el tiempo y el inter´s o e de la hipoteca que est´n en la Vista. El Controlador decide que datos necesita de la Vista para llevar a cabo la tarea como respuesta a la interacci´n del usuario. La l´gica del negocio programada en el Controlador indica que si el usuario o pulsa el bot´n Calcula se debe recuperar la cantidad. EL PATRON DE DISENO MODELO/VISTA/CONTROLADOR 169 Figura 11. La Vista pide los datos de su inter´s para visualizarlos. .6. el tiempo y el inter´s de la hipoteca y e pulsa el bot´n Calcula. 5. El usuario introduce la cantidad. El Controlador env´ estos datos al Modelo para que calcule la nueva ıa cuota. La Vista informa al Controlador de que el usuario ha pulsado el bot´n o Calcula. La Vista pide la nueva cuota y la visualiza. o 2. Figura 11. o 4. a 4. 5.

Para dejar a´n m´s clara la potencia u a de este patr´n. en la Figura 11.170 ´ CAP´ ITULO 11. este cambio ser´ totalmente transparente tanto para el Controlador como para a el Modelo. gracias a esta divisi´n de responsabilidades los posibles cambios en la o implementaci´n de uno de los actores es completamente transparente al resto. Que un actor tenga conocimiento de los otros implica que tendr´ una referencia hacia el actor a con el que necesita intercambiar mensajes. o Imagina por ejemplo que hay un cambio en la Vista. la Vista debe o n conocer tanto al Controlador como al Modelo. vamos a implementar las referencias a una interface y no a una o clase concreta. o . INTERFACES GRAFICAS DE USUARIO Figura 11. la Figura 11. este patr´n puede resultar farragoso. si despu´s de cambiar.EXIT ON CLOSE) para cerrar la aplicaci´n cuando el usuario cierra la ventana?. es todo lo o contrario. o n Aunque en un primer momento. o pao recernos que hay muchas idas y venidas entre el c´digo de los actores. es decir. Por su lado.6 no hay ninguna flecha que salga desde el Modelo hacia el Controlador.7: Diagrama UML para el patr´n de dise˜o MVC. de hecho. 1. F´ ıjate que para poder implementar este patr´n de dise˜o.7 muestra el esquema de clases citado. la funcionalidad que un actor ofrece la vamos a recoger en un interface y adem´s tendremos la clase concreta que implementar´ el a a interface. En el Ap´ndice B se encuentra el c´digo fuente de la aplicaci´n del c´lculo e o o a de la cuota mensual de una hipoteca. ¿Cuales son las ventajas y desventajas de utilizar el m´todo de convee niencia setDefaultCoseOperation(JFrame. y por su parte el Controlador debe conocer tanto a la Vista como al Modelo. Cuestiones. la e Vista sigue proporcion´ndonos los datos sobre los que efectuar el c´lculo y le a a podemos seguir informando de los cambios en el Modelo para que se actualice. el unico actor que ´ necesita conocer el Modelo es a la Vista.

El c´digo del c´lculo de la cuota mensual de una hipoteca mostrado en o a el Ap´ndice B sigue la estrategia de no enviar datos desde la Vista al e Controlador cuando se produce el evento de pulsar el bot´n Calcula. al informar a la Vista no le env´ el nuevo valor de ıa la cuota mensual de la hipoteca. Recupera el ejercicio de la agenda telef´nica y crea un interfaz gr´fico de o a usuario para ella. ¿Cuales son las desventao jas?. o n . Lo mismo ocurre cuando el Modelo o o cambia su estado.´ ˜ 11. la Vista no env´ la cantidad hipoteca. Lecturas recomendadas. Ejercicios. El cap´ ıtulo 1 de la referencia [8] presenta el patr´n de dise˜o MVC hao n ciendo referencia al resto de patrones que utiliza. es ıa e el Controlador quien pide estos datos una vez que la Vista le informa de que el usuario puls´ el bot´n Calcula. 1. La referencia [3] tambi´n presenta de modo riguroso y muy ameno el e patr´n de dise˜o MVC. ¿Cuales son las ventajas de esta aproximaci´n?.6. el tiempo ni el inter´s. EL PATRON DE DISENO MODELO/VISTA/CONTROLADOR 171 2. es o decir. simplemente le informa de que hay un nuevo valor disponible y es finalmente la Vista quien pide el nuevo valor al Modelo.

INTERFACES GRAFICAS DE USUARIO .172 ´ CAP´ ITULO 11.

y c´mo. . ¿Qu´ son los Applets? e Los Applets son aplicaciones Java que se ejecutan en el contexto de un navegador web.html. . .3. el primer contacto con Java fue a trav´s de los e Applets. . . http:// openastexviewer. 173 174 175 176 176 177 Introducci´n o Para muchos de nosotros. Comunicaci´n entre Applets . en el caso de los Applets.4.5. 12. .com/mathphysics. Ciclo de vida de un Applet . . Convertir una aplicaci´n Swing en un Applet o 12. 12. . . . . Algunos ejemplos se pueden encontrar en las siguientes direcciones: http://www. . . . y es el navegador web el encargado de descargar las clases del Applet desde la url especificada. . esos peque˜os programas que se ejecutan dentro de una p´gina web y n a con los que se puede interaccionar. . a a 12. . particularidades.6.net/web/thinlet. . . . . . En este cap´ ıtulo se va a presentar la programaci´n de Apples. iniciar una instancia de la m´quina virtual a de Java y ejecutar el Applet. . ¿Qu´ son los Applets? . Lectura de par´metros de la p´gina HTML . sus caraco ter´ ısticas. . descargas un programa que no sabes 173 . . .Cap´ ıtulo 12 Applets Contenidos 12. . . . . es un importante factor a tener en cuenta.falstad. . . . . .2. e 12. . . . . . . o 12. . . C´digo HTML para contener un Applet . . . F´ a a ıjate el riesgo que en principio se corre si no hubiese restricciones de seguridad. o .1. . La seguridad. . A trav´s de c´digo HTML reservamos una zona de la p´gina web para e o a visualizar el Applet. . . Para ejecutar un Applet es necesario descargar desde la web las clases que se ejecutar´n en nuestra m´quina. con poco trabajo extra podemos convertir o nuestras aplicaciones Swing en Applets siempre que se cumpla una serie de restricciones.1.html.

APPLETS quien ha escrito ni con qu´ prop´sito y lo ejecutas en tu m´quina. un Applet tiene las siguientes restricciones de seguridad: Un Applet no puede leer del disco duro del cliente. o El ciclo de vida de un Applet est´ directamente relacionado con las llamadas a que el navegador web hace a m´todos del Applet. el navegador web llama a este m´todo cuando el e Applet ha sido efectivamente cargado. El hecho de que los Applets se ejecuten en el contexto de un navegador web implica que su ciclo de vida no es el de una aplicaci´n de escritorio. a a 12. public void stop(). o public void paint(Graphics g). Un Applet no puede acceder a la informaci´n privada del usuario. y nos permite el acceso al contexto gr´fico de bajo nivel Graphics. Si no hubiesen e o a restricciones de seguridad un programa malicioso podr´ acceder a tu disco duro ıa para leer informaci´n personal. o podr´ borrar o modificar ficheros.174 CAP´ ITULO 12. Por todo lo anterior. Un Applet no puede abrir conexiones de red a ning´n otro servidor salvo u aquel desde el que se descarg´. el navegador web llama a este m´todo antes de e eliminar el Applet de memoria. a public void destroy(). o escribir o ıa en tu disco duro. para forzar su llamada utilizaremos el m´todo public void e e repaint(). el navegador web llama a este m´toe do cada vez que se debe dibujar el contenido del Applet. Este m´todo es el primero que se e invoca en un Applet. el navegador web llama a este m´todo para indicar e que el Applet debe detener su ejecuci´n. en cuyo caso se llamar´ previamente al a m´todo stop(). e Para que una de nuestras clases sea un Applet debe extender a la clase JApplet que define los siguientes m´todos relacionados con su ciclo de vida: e public void init(). e . Un detalle muy ima portante es que desde nuestro c´digo nunca llamaremos directamente a o este m´todo. o Un Applet no puede ejecutar aplicaciones en el cliente. cuando se abandona o la p´gina web que contiene el Applet. public void start(). por ejemplo. tal y como hemos visto. como las que ya hemos aprendido a programar. el navegador web llama a este m´todo para indie carle que debe empezar su ejecuci´n. Un Applet no puede escribir al disco duro del cliente. o Estas restricciones de seguridad y el hecho de que finalmente el Applet se ejecutar´ en un M´quina Virtual Java los hacen muy seguros.2. Ciclo de vida de un Applet Un Applet se ejecuta en el contexto de un navegador web y tiene fuertes restricciones de seguridad.

CODIGO HTML PARA CONTENER UN APPLET 175 Figura 12.3. align. . como veremos en la siguiente secci´n. a Otros atributos de la etiqueta <applet> que nos pueden ser de utilidad son: alt. Para programar de modo eficiente un Applet debemos seguir estas reglas: los recursos que el Applet necesita para su ejecuci´n deben ser creados en su m´todo o e init(). e 12. muestra un texto alternativo si el navegador no puede visualizar el Applet. y mediante las etiquetas width y height especificamos el ancho y alto o dentro de la p´gina web reservado para la visualizaci´n del Applet.3. </ a p p l e t> </ body> </ html> Listado 12.1: C´digo HTML que muestra la aplicaci´n de la hipoteca dentro de o o una p´gina web. desde nuestro c´digo. e La Figura 12. e Nunca llamaremos.´ 12. El atributo achive nos sirve para indicar el fichero empaquetado de nuestra aplicaci´n. para ellos utilizaremos el m´todo repaint(). y esos mismos recursos deben ser liberados en su m´todo destroy(). h i p o t e c a . j a r " c o d e=" a p p l e t s . a hspace. el margen a la izquierda y derecha del Applet en unidades de p´ ıxeles. C´digo HTML para contener un Applet o Para poder visualizar un Applet al cargar una p´gina HTML debemos utilizar la a etiqueta <html> como se muestra en el Listado 12. con la etiqueta code o especificamos la clase que implementa el Applet. H i p o t e c a A p p l e t " width =519 h e i g h t =65> S i p u e d e s v e r e s t o tu n a v e g a d o r no s o p o r t a Java .1 muestra gr´ficamente el orden de las llamadas entre los m´toa e dos que constituyen el ciclo de vida de un Applet. el alineado del Applet dentro de la p´gina web.1.1: Llamada a los m´todos de un Applet durante su ciclo de vida. a o <html> <head> < t i t l e>El p r i m e r a p p l e t</ t i t l e> </ head> <body> <a p p l e t a r c h i v e=" h i p o t e c a . al m´todo paint(Graphics g) para o e forzar el dibujado del Applet.

2 muestra c´mo convertir la o aplicaci´n Swing del Listado B. 12. o los definiremos en el c´digo HTML que contiene al Applet. y lo que podemos visualizar a es. Un Applet no tiene constructores.5. Este es un sencillo recetario para convertir una aplicaci´n Swing en un Apo plet: 1. como veremos en la Secci´n a o 12. el c´digo dentro del constructor en la o aplicaci´n Swing lo escribiremos dentro del m´todo public void init() o e del Applet. con pocas modificaciones. al t´ ıtulo de esta (setTitle(String titulo). el margen superior e inferior del Applet en unidades de p´ ıxeles. podremos. por ejemplo <param name="saludo"value="Hola/>.. . No podemos hacer uso de JFrame. entre otras cosas un interfaz gr´fico de usuario. el Listado 12. APPLETS vspace. es una aplicaci´n Java con la particularidad de a o que se ejecuta en el contexto de un navegador web. en vez de esta clase utilizaremos JApplet. ya que la posici´n y el tama˜o del Applet o o n se especifican dentro del c´digo HTML. Siguiendo estos sencillos pasos. Un Applet no puede tener escuchadores de tipo WindowListener.4. Un Applet tiene una zona.6. Lectura de par´metros de la p´gina HTML a a La etiqueta <applet> puede contener otras etiquetas de inter´s adem´s de las e a que ya hemos visto. Esto nos permite definir par´metros de entrada a nuestro a Applet sin necesidad de modificar el c´digo de nuestro Applet. el nombre del Applet. Con la etiqueta <param> especificamos un par´metro con a su valor. donde se va a visualizar. transformarla en un Applet. o su posici´n (setLocation(int. si a una aplicaci´n Swing cumple con las restricciones de seguridad impuestas a los o Applets. 2. Convertir una aplicaci´n Swing en un Apo plet Un Applet. en vez de ello.176 CAP´ ITULO 12. No se pueden utilizar m´todos de JFrame relativos al tama˜o de la ventana e n (setSize(.. o 4.7 del Ap´ndice B del c´lculo de la cuota mensual o e a de una hipoteca en un Applet. o a o e 12. a efectos pr´cticos.6 se mostrar´ c´mo hacer uso de esta t´cnica. o En la Secci´n 12. int). name.)). dentro de la p´gina web. Dicho de otro modo. h i p o t e c a . Etiqueta importante en la comunicaci´n entre o Applets que residen en la misma p´gina web. 3. 1 2 package a p p l e t s . Desde el c´digo o de nuestro Applet podremos leer los par´metros definidos dentro de la etiqueta a Applet con el m´todo String getParameter(String nombreParametro) que e recibe como argumento el nombre del par´metro que queremos leer ("saludo" a en el ejemplo anterior).

v i s t a . Modelo . A c t i o n E v e n t . import j a v a .hipoteca. ModeloImpl .6. setControlador ( controlador ) . getContenedor ( ) ) . . setContentPane ( v i s t a . Este m´todo pertenece al contexto e donde se est´ ejecutando el Applet.hipoteca. c o n t r o l a d o r . .2 a muestra c´mo se visualiza la p´gina web en un navegador.3 muestra un sencillo ejemplo de comunicaci´n entre Applets o residentes en la misma p´gina web mostrado en el Listado 12. controlador . Modelo modelo = new ModeloImpl ( ) . v i s t a . @Override public void i n i t ( ) { V i s t a v i s t a = new V i s t a I m p l ( ) .2: Applet con la aplicaci´n del c´lculo de la cuota mensual de una o a hipoteca Como tuvimos cuidado de aislar todo lo relativo al actor Vista siguiendo el patr´n de dise˜o MVC.6. v i s t a . 12. . .controlador. la transformaci´n de aplicaci´n Swing a Apo n o o plet ha sido muy sencilla. . J L a b e l . import j a v a x . . controlador . import import import import import import gui gui gui gui gui gui . gui. . C o n t r o l a d o r c o n t r o l a d o r = new C o n t r o l a d o r I m p l ( ) . JButton . VistaImpl . awt . hemos podido aprovechar todas las clases dentro los paquetes gui. modelo .4. c o m u n i c a c i o n . modelo . controlador . COMUNICACION ENTRE APPLETS 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 177 import j a v a x . import j a v a x . A c t i o n L i s t e n e r . que no es otra cosa que la propia p´gina a a web. hipoteca hipoteca hipoteca hipoteca hipoteca hipoteca . awt . awt . J A p p l e t . s w i n g . Controlador . s w i n g . . s e t M o d e l o ( modelo ) . Comunicaci´n entre Applets o Applets que residen dentro de la misma p´gina web pueden obtener referencias a a los otros Applets dentro de la misma p´gina y a trav´s de estas referencias a e un Applet puede llamar a los m´todos de otro Applet dentro de la misma p´gie a na web. . Para ello utilizaremos el m´todo Applet getApplet(String nombre) e que recibe como argumento el nombre del Applet del que queremos obtener una referencia. import j a v a x . s w i n g . Vista .hipoteca. Recuerda que el nombre de un Applet lo podemos definir con el atributo name de la etiqueta <applet>. import j a v a . Para obtener este contexto desde un Applet utilizamos el m´todo public e AppletContext getAppletContext(). modelo . ControladorImpl . . BorderLayout . . s e t M o d e l o ( modelo ) .vista y gui.modelo. J A p p l e t . El Listado 12. public c l a s s H i p o t e c a A p p l e t extends J A p p l e t { private s t a t i c f i n a l long s e r i a l V e r s i o n U I D = 1L . import j a v a . o a 1 2 3 4 5 6 7 8 9 package a p p l e t s . s w i n g . e v e n t . de hecho. } } Listado 12. setVista ( vista ) . s e t V i s t a ( v i s t a ) . vista . e v e n t . La Figura 12.´ 12.

getText ( ) ) . j b E n v i a r . } public void r e c i b e M e n s a j e ( S t r i n g m e n s a j e ) { j l E l D i c e . . ´ j t f T u D i c e s = new J T e x t F i e l d ( 5 0 ) . setText ( " M e n s a j e : " + mensaje ) . add ( miEntrada . miEntrada . add ( suEntrada . " ) . APPLETS import j a v a x . add ( j b E n v i a r ) . J P a n e l c o n t e n e d o r = new J P a n e l (new BorderLayout ( ) ) . C o m u n i c a c i o n A p p l e t s " width =800 h e i g h t =70 name=" I n f e r i o r "> <param name=" E l O t r o " . } } } Listado 12. j a r " c o d e=" a p p l e t s . getApplet ( getParameter ( " ElOtro " ) ) . elOtro . add ( j t f T u D i c e s ) . @Override public void i n i t ( ) { J P a n e l miEntrada = new J P a n e l ( ) . private J T e x t F i e l d j t f T u D i c e s . c o n t e n e d o r .178 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 CAP´ ITULO 12. add ( j l E l D i c e ) . . setContentPane ( contenedor ) . J P a n e l . import j a v a x . </ a p p l e t > <br /> <a p p l e t a r c h i v e=" c o m u n i c a c i o n A p p l e t s . s u E n t r a d a . BorderLayout . public c l a s s C o m u n i c a c i o n A p p l e t s extends J A p p l e t { private s t a t i c f i n a l long s e r i a l V e r s i o n U I D = 1L . miEntrada . JButton j b E n v i a r = new JButton ( " E n v i a r " ) .3: C´digo HTML de la p´gina visualizada en la Figura 12. repaint () . . a d d A c t i o n L i s t e n e r (new E s c u c h a d o r ( ) ) . c o m u n i c a c i o n . private C o m u n i c a c i o n A p p l e t s e l O t r o = n u l l . miEntrada . add (new J L a b e l ( " T u d i c e s : " ) ) . c o n t e n e d o r .SOUTH) . J P a n e l s u E n t r a d a = new J P a n e l ( ) . c o m u n i c a c i o n .2 o a <html> <head> 3 < t i t l e >C o n v e r s a c i ´ n e n t r e A p p l e t s </ t i t l e > o 4 </head> 1 2 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <body> <a p p l e t a r c h i v e=" c o m u n i c a c i o n A p p l e t s . J T e x t F i e l d . s w i n g . C o m u n i c a c i o n A p p l e t s " width =800 h e i g h t =70 name=" S u p e r i o r "> <param name=" E l O t r o " v a l u e=" I n f e r i o r " /> S i p u e d e s v e r e s t o tu n a v e g a d o r no s o p o r t a Java . BorderLayout . recibeMensaje ( jtfTuDices .NORTH) . private J L a b e l j l E l D i c e . j l E l D i c e = new J L a b e l ( " E s c u c h a n d o . s w i n g . } private c l a s s E s c u c h a d o r implements A c t i o n L i s t e n e r { @Override public void a c t i o n P e r f o r m e d ( A c t i o n E v e n t e ) { i f ( e l O t r o == n u l l ) elOtro = ( ComunicacionApplets ) getAppletContext ( ) . j a r " c o d e=" a p p l e t s .

oracle.2: Llamada a los m´todos de un Applet durante su ciclo de vida.´ 12. Convierte la aplicaci´n de la Agenda en un Applet para que puedas intero accionar con ella a trav´s de un navegador web.html podr´s encontrar toda la informaci´n a o necesaria para programar Applets. </a p p l e t > </body> </html> Listado 12. COMUNICACION ENTRE APPLETS 179 Figura 12. e 27 28 29 30 31 v a l u e=" S u p e r i o r "/> S i p u e d e s v e r e s t o tu n a v e g a d o r no s o p o r t a Java . .4: Applet con la aplicaci´n del c´lculo de la cuota mensual de una o a hipoteca Ejercicios.com/javase/tutorial/ o deployment/applet/index. e Lecturas recomendadas.6. En esta direcci´n web http://download. 1.

180 CAP´ ITULO 12. APPLETS .

1.1. Beneficios de la combinaci´n de Bugzilla y MyLyn o desde Eclipse . . MyLyn es una herramienta. .2. . . . . . .1. .2. . . . . . . . . . . . .1. . Trabajo con MyLyn y Bugzilla desde Eclipse . . . . .2. . . . . Trabajar con Working Sets . 13.1. . . Trabajar con Bugzilla . . . . . . 13.1. . . 13. . . .1. . . . . . . .3.3. n 13. . . . Instalaci´n de Bugzilla . 13. . . 13. . Trabajar con MyLyn .2. . . 13. 13. . Trabajar con categor´ .2. . .1. . . . . . . . . Sistema de gesti´n de errores Bugzilla . . A˜adir errores a Bugzilla desde Eclipse . . . . Cual es el objetivo de MyLyn . . . . Acceso a Bugzilla desde MyLyn y Eclipse . . . . integrada en Eclipse a trav´s de un plug-in. . . . .3. . . o 13. . . . .2. . Recuperar errores desde Bugzilla como tareas en MyLyn . . . . Cual es el objetivo de Bugzilla . . . . . . o 13.2. . . . . navegar por le c´digo para encontrar un m´todo o o e una clase puede llegar a consumir mucho tiempo. . .3. . . . . . . . . . . .2.2. . . .Cap´ ıtulo 13 Control de errores con MyLyn y Bugzilla Contenidos 13. . . Sistema de control de tareas MyLyn .2. . . .3.3. . cuando se trabaja en proo o yectos cuyo c´digo est´ organizado en un gran n´mero de clases dentro de sus o a u correspondiente paquetes. . . que oculta el c´digo que no es ree o levante a la tarea que estamos llevando a cabo. . . 181 . . ıas 13. 13. . . . . . 182 182 182 182 186 187 188 188 188 195 199 201 201 201 201 Introducci´n o Los Entornos de Desarrollo Integrado son una excelente herramienta para la creaci´n y mantenimiento de c´digo. . . . . . . . Aunque MyLyn es mucho m´s a que eso.2. . . Trabajar con tareas . . Sin embargo. . . . .1. . . . . .2. .1. .1. 13. .2. . 13. . . .2.3.

Bugzilla es una excelente herramienta o o que cumple esta funci´n. El n´mero total de ficheros u u con c´digo fuente puede ser muy elevado. a 13. Si no aparece esta vista por defecto..2. Pero MyLyn no es s´lo eso. ıas Veamos c´mo trabajar con cada uno de estos nuevos conceptos. Cual es el objetivo de MyLyn Cuando trabajamos en equipo y en grandes proyectos es usual que el c´digo o fuente del proyecto est´ organizado en un gran n´mero de paquetes. Al descargarnos Eclipse nos estamos descargando tambi´n esta herrae mienta. el objetivo de MyLyn es permitir concentrarnos s´lo en el c´digo o o de un proyecto sobre el que estamos trabajando. cuando desarrollamos o una tarea dentro de un proyecto de gran envergadura. Trabajar con tareas Lo primero que vamos a hacer es crear una nueva tarea. o Quiz´s. dentro de e u los cuales encontramos un gran n´mero de clases.182CAP´ ITULO 13. puedes hacerla visible seleccionando la opci´n que se muestra en la Figura 13.1. 13. o A continuaci´n se nos abrir´ la ventana que se muestra en la Figura 13.1.. si no un sistema de control de trabajo que podemos utilizar bien de o forma local o bien en conexi´n con un sistema de control de errores. Lo que estamos haciendo o en este punto es indicarle a MyLyn que la tarea que estamos creando es local a .1. Trabajar con MyLyn MyLyn dispone de una vista propia en Eclipse. una tarea importante en todo proyecto inform´tica es el seguia miento y gesti´n de errores en el c´digo. o o o 13. o La nueva vista que se abrir´ en Eclipse se muestra en la Figura 13. CONTROL DE ERRORES CON MYLYN Y BUGZILLA Por otro lado. Y es en este o ultimo caso cuando Bugzilla se convierte en una herramienta imprescindible.2. lo mejor de ambas herramientas es la posibilidad de combinarlas a dentro de Eclipse de tal manera que podemos inicial el seguimiento de un error en Bugzilla desde el propio Eclipse y darlo de alta como una tarea en MyLyn para poder centrar nuestra atenci´n s´lo en el c´digo relativo a ese error. En esencia.1. ocultando el resto del c´digo del o proyecto que no es relevante a la tarea que estamos llevando a cabo.1. s´lo son relevantes a esta o tarea un n´mero reducido de ficheros frente al total. para ello.. Si el entorno de desarrollo u que estamos utilizando nos presenta todos los ficheros del proyecto. podemos perder bastante tiempo navegando por ellos y cribando los que s´ son relevantes ı a nuestra tarea.4 o a donde debemos seleccionar la opci´n por defecto Local. ´ En MyLyn la unidad b´sica de trabajo es la tarea. El nombre de esta vista es Task List.1. o 13. Generalmente. Sistema de control de tareas MyLyn MyLyn es una potente herramienta que se encuentra en el paquete b´sico de a Eclipse.1. despliega el icono que se muestra en la Figura 13. Las tareas se pueden a organizar en categor´ y estas a su vez se pueden agrupar en grupos de trabajo.2.3 y selecciona la opci´n New Task.

13.2: Aspecto de la vista Task List de MyLyn.1.1: Opci´n de men´ para abrir la vista de MyLyn. o u Figura 13. . SISTEMA DE CONTROL DE TAREAS MYLYN 183 Figura 13.

5 donde podemos introducir las propiedades de la nueva tarea.3. Antes de ver c´mo crear nuevas categor´ veamos cual es el trabajo b´sico o ıas a con las tareas. se nos abrir´ la ventana mostrada en la a Figura 13. u o Campo de comentarios. Estimate: n´mero de horas estimadas de dedicaci´n a la tarea. que puede ser Completo o Incompleto. con relleno blanco la primera vez. Status: el estado de la tarea.6. CONTROL DE ERRORES CON MYLYN Y BUGZILLA Figura 13. ¿C´mo lo consigue? Ocultando el c´digo que no hemos modificado o o o consultado en el desarrollo de la tarea. que se encuentra a la izquierda del nombre de la tarea. podemos guardarla. Scheduled : cuando est´ planificado que trabajaremos en la tarea.3: Creaci´n de una nueva tarea en MyLyn. la vista a Package Explorer ha ocultado toda la informaci´n relativa a la organizaci´n de o o los paquetes y las clases en ella contenida. por un lado. no estamos utilizando ning´n repositorio externo. Para activar una tarea pulsa el icono con aspecto de c´ ırculo. o nuestra m´quina de desarrollo. En esta ventana podemos definir las siguiente propiedades para la nueva tarea: Nombre de la tarea. MyLyn nos permite concentrarnos s´lo en el c´digo que necesio o tamos para desarrollar una determinada tarea. Una vez definidas estas propiedades de la nueva tarea. a u La creaci´n de tareas en repositorios externos la cubriremos en la secci´n 13. Observa tambi´n que el bot´n de e o tarea activa de MyLyn mostrado en la Figura 13. pulsa sobre el icono mostrado ıa en la Figura 13. Para desactivar el filtro. Abre a ıa . a Due: en que fecha debe estar completada la tarea. y al hacerlo. Como es la primera vez que activamos la tarea. de modo a n autom´tico. MyLyn oculta toda u o la jerarqu´ de paquetes. Ver´s que ocurren varios cambios en Eclipa se. se mostrar´ de nuevo la jerarqu´ completa de clases. y no hemos modificado o consultado ning´n c´digo. todas las tareas que no se han asignado a ninguna categor´ a ıa. MyLyn nos permite concentrarnos s´lo en el c´digo relacionado con la tarea que activa en cada o o momento. En esta carpeta se a˜aden. o o Tras seleccionar el repositorio local.6 est´ pulsado.184CAP´ ITULO 13. a ¿Qu´ ha ocurrido al activar la tarea? ¿Por qu´ han desaparecido todas las e e clases de la vista Package Explorer ? Como hemos comentado. el aspecto del icono a la izquierda de la tarea cambia de aspecto para mostrar una esfera sombreada en gris. veremos que se actualiza la vista Task List con la nueva tarea. Y lo que es m´s importante. que aparecer´ en la carpeta Uncategorized.

o n a Figura 13.1.4: Selecci´n del repositorio donde se a˜adir´ la nueva tarea. SISTEMA DE CONTROL DE TAREAS MYLYN 185 Figura 13.5: Definici´n de las propiedades de una nueva tarea en MyLyn.13. o .

los m´todos sobre los que no has trabajado al desarrollar la tarea se e colapsar´n. Eclipse te mostrar´ todos los proyectos. Para a˜adir. Realiza alg´n cambio en el u c´digo de la clase.2. el c´digo de una clase y activa de nuevo el filtro. si lo e activas. n o simplemente pincha sobre la tarea y arr´strala hasta la categor´ deseada.6: Tarea activa en MyLyn MyLyn. ıa . Modelo de datos. Si activas de nuevo la tarea. Por defecto. pulsando en el icono a la izquierda de la tarea en la vista Task List. la tarea se crear´ en ıa a la categor´ actualmente seleccionada. otra categor´ o a ıa relativa a las tareas relacionadas con el modelo de datos de nuestra aplicaci´n o y as´ sucesivamente.7. ver´s que en la vista Package o n u a Explorer aparecen s´lo los m´todos en los que has a˜adido comentarios. una tarea ya existente. MyLyn recuerda el estado en que a o o qued´ la informaci´n de trabajo relacionada con la tarea en el momento de su o o desactivaci´n.2. como a˜adir alg´n comentario. Observa que en el editor tambi´n aparece el icono de filtro de MyLyn. Esta es la base de la potencia de e MyLyn presentar s´lo el c´digo de las clases que hemos modificado o consultado o o al desarrollar una determinada tarea. Ver´s que todas las clases se o a ocultan excepto aquella que aparece en el editor. o 13. CONTROL DE ERRORES CON MYLYN Y BUGZILLA Figura 13. Para ıa. por ejemplo. por ejemplo. Como nombre de la categor´ introduzcamos. Ver´s a ıa a que la descripci´n de la tarea se actualiza para dar cuenta de la categor´ a la o ıa que pertenece. Finalmente. ıas un proyecto concreto podemos. ıa Al pulsar el bot´n Ok observar´s que se ha creado una carpeta con ese nombre en o a la vista Task List. crear una categor´ relativa a las ıa tareas relacionadas con la creaci´n del interface gr´fico de usuario.186CAP´ ITULO 13. s´lo se mostrar´ el c´digo de aquellos m´todos que has modificado a o a o e o consultado. Para crear una tarea dentro de una determinada categor´ simplemente ıa. Una tarea s´lo puede pertenecer ıas o a una categor´ Las categor´ nos sirven para estructurar las tareas. si desactivas la tarea.1. Eclipse te mostrar´ s´lo el c´digo relacionado con ella. el reso e n to de m´todos de la clase permanece oculto. paquetes a y clases en la vista Package Explorer. ı Para crear una nueva categor´ despliega la opci´n de creaci´n de nuevos ıa o o elementos en la vista Task List y selecciona la opci´n New Cathegory tal y o como muestra la Figura 13. selecciona la categor´ antes de crear la tarea. Trabajar con categor´ ıas Las categor´ son agrupaciones de tareas. o cambiar de ubicaci´n.

o 13. pulsa el bot´n Ok. Trabajar con Working Sets Por encima de las categor´ existe un nuevo escal´n que nos permite organizarıas o las en nuevos grupos. Introduce un nombre para este nuevo Working Set y selecciona las categor´ Vista y Modelo de datos. SISTEMA DE CONTROL DE TAREAS MYLYN 187 Figura 13. a Pulsa el bot´n New para crear un nuevo Working Set. F´ ıjate que las tareas s´lo pueden pertenecer a una unica o ´ categor´ una tarea no puede estar en m´s de una categor´ Los Working Sets ıa. se abrir´ la ventana o a mostrada en la Figura 13. ıa a Working Set. si lo seleccionas s´lo te aparecer´n las a o a categor´ Modelo de datos y Vista que son las que has incluido en este Working ıas .8 pero esta vez podr´ ver el nuevo a a Working Set reci´n creado. ıa Supongamos que tenemos una jerarqu´ de tareas y categor´ como la mosıa ıas trada en la Figura 13. Volver´s a la ventana de la Figura 13. Se abrir´ la ventana de la Figura 13.3. Pulsa el tri´ngulo negro a la izquierda del enlace All para desplegar las a opciones y selecciona Edit. a ıa.8: Creaci´n de un Workin Set en MyLyn. si despliegas de nuevo la e o lista de Working Sets (tri´ngulo a la izquierda del enlace All de la Figura 13.9. Ahora.1.7: Creaci´n de una nueva categor´ en MyLyn.2. o ıa Figura 13. Para acabar pulsa el bot´n ıas o Finish.8. La pertenencia de una categor´ a un Working Set no es exclusiva.13.8 a ver´s el nombre del nuevo Working Set. nos permiten agrupar categor´ y una categor´ puede pertenecer a m´s de un ıas.1.10.

13.org.2. Durante el ciclo de vida del software. Como ves. Sistema de gesti´n de errores Bugzilla o Bugzilla es una herramienta libre y de c´digo abierto utilizada por grandes o compa˜´ nıas. la ultima versi´n estable de Bugzilla es a ´ o la 4. o o Set. Eclipse proporciona n por defecto este conector. 13.1. Afortunadamente. Apache o Eclipse. una de las etapas b´sicas es la detecci´n y soluci´n de errores.2.9: Selecci´n y edici´n de un Workin Set en MyLyn. ll´malo Relaci´n entre Modelo a o y Controlador y a˜ade a ´l s´lo las categor´ Modelo y Controlador.bugzilla. n e o ıas la categor´ Modelo est´ dentro de dos Working Sets. Se puede trabajar con Bugzilla desde un navegador web o bien desde un cliente como MyLyn si se dispone del conector adecuado. Para o o otros sistemas operativos o versiones de Linux consultar los detalles en la p´gina a web de Bugzilla. y no es de extra˜ar. que se puede descargar desde http://www. En esta secci´n se muestra c´mo instalar Bugzilla en Ubuntu 10.2. el resto de categor´ no se visualiza. como Mozilla. Bugzilla a o o nos permite gestionar y automatizar el seguimiento de errores hasta su resoluci´n o final.0. Cual es el objetivo de Bugzilla Bugzilla es un sistema de seguimiento de errores.188CAP´ ITULO 13.2. Instalaci´n de Bugzilla o En el momento de escribir estas p´gina. CONTROL DE ERRORES CON MYLYN Y BUGZILLA Figura 13.10. . ıas Puedes probar a crear un nuevo Working Set. ıa a 13.

10. v5.10: Propiedades de un Workin Set en MyLyn. El primero de ellos es perl.10.perl. a . which may be found in the Perl 5 source kit. point your browser at http://www. the Perl Home Page.´ 13. o Bugzilla necesita al menos la versi´n 5. SISTEMA DE GESTION DE ERRORES BUGZILLA 189 Figura 13.org/. should be found on this system using "man perl" or "perldoc perl". para comprobar si tenemos perl instalado abrimos un terminal y escribimos: $perl -v This is perl. Si perl no est´ instalado lo podemos o a instalar tecleando en el terminal: $sudo apt-get install perl F´ ıjate que para instalar nuevos paquetes en linux necesitamos permiso de superusuario. Complete documentation for Perl.8. Antes de proceder a la instalaci´n se ı o nos preguntar´ por la clave de superusuario. Larry Wall Perl may be copied only under the terms of either the Artistic License or the GNU General Public License.2.1 de perl instalada. including FAQ lists. Si podemos ver lo anterior es que tenemos la versi´n 5.1 (*) built for i486-linux-gnu-thread-multi Copyright 1987-2009. If you have access to the Internet. Antes de instalar Bugzilla necesitamos instalar algunos paquetes de los que depende Bugzilla. de ah´ que utilicemos sudo.

Esta clave de acceso a la utilizaremos m´s tarde en la configuraci´n de Bugzilla./checksetup.1.tar. /var/www1 .mozilla. Para descomprimir este fichero escribe en el terminal: $ tar -xvf bugzilla-4. es un gestor de bases de datos.gz.190CAP´ ITULO 13. para o ello sit´ate en el directorio /var/www/bugzilla-4.0. lo podemos instalar tecleando: apt-get install mysql-admin mysql-client mysql-server Lo anterior nos instalar´ tanto el gesto de bases de datos como el cliente a y las herramientas de administraci´n. de nuevo. Si no lo tenemos.0 y escribe en el terminal: u $sudo . El siguiente paso para a tener Bugzilla a punto es instalar los m´dulos perl que necesita Bugzilla.2. en el caso de la distribuci´n de Linux Ubuntu 10. o .2.gz Observar´s que se ha creado el directorio bugzilla-4.org/ webtools/bugzilla-4.org/pub/mozilla.tar. Si no fuese el caso lo puedes o instalar tecleando en el terminal $sudo apt-get install apache2 En este punto.0. ya tenemos instalados todos los paquetes necesarios para poder trabajar con Bugzilla.16. el mensaje nos indica que tenemos instalado el servidor web Apache en nuestro sistema en su versi´n 2. Vamos a utilizar MySQL aunque tambi´n es posible utilizar e PostgreSQL.pl ?check-modules 1 Para otras distribuciones de Linux y sistemas operativos consultar la documentaci´n.41.14 Distrib 5. Para ello. escribe en un terminal: $apache2 -v Server version: Apache/2. si no lo tenemos ya instalado. for debian-linux-gnu (i486) using readline 6. Durante la instalaci´n de MySQL se nos o o pedir´ que definamos la clave de acceso del administrador.gz Al acabar la descarga ver´s que tienes un fichero comprimido con nombre a bugzilla-4.1 Lo anterior nos indica que tenemos instalada la versi´n 5.0.41 de este gestor o de bases de datos.0. Para comprobar si MySQL est´ instalado escribimos de nuevo en a un terminal: $mysql --version mysql Ver 14.16 (Ubuntu) Server built: Nov 18 2010 21:17:43 En este caso. Lo siguiente es descargar y configurar Bugzilla.10.1. El directorio por defecto donde el servidor web Apache busca los ficheros solicitados es.tar. CONTROL DE ERRORES CON MYLYN Y BUGZILLA Lo siguiente que debemos instalar. o Sit´ate en ese directorio y descarga Bugzilla escribiendo en un terminal lo siu guiente: $sudo wget http://ftp. a o El siguiente paso es comprobar si tenemos instalado el servidor web Apache.

SISTEMA DE GESTION DE ERRORES BUGZILLA 191 Te aparecer´ una lista con los m´dulos necesarios y los opcionales que necea o sita Bugzilla.00 sec) Para ver todas las bases de datos que gestiona MySQL escribe: . El siguiente paso es crear la base de datos que manejar´ Bugzilla.pl ?all En este punto necesitamos instalar los m´dulos perl necesarios para Apache. Query OK. Escribe en un terminal: $ sudo mysql -u root -p Se te solicitar´ la clave de administrador que has introducido en la instalaci´n a o de MySQL.pl Con ello.´ 13. $db_pass = ?clave de administrado de MySQL?./checksetup. Una vez introducida con ´xito nos encontraremos en el ambiente del e cliente de MySQL. Para crear la base de datos que manejar´ Bugzilla escribe: a mysql> create database bugs.pl Apache2::SizeLimit Con todo esto ya podemos continuar con la instalaci´n de Bugzilla. Tal y como se indica al final de la lista de m´dulos.2.0. puedes instalar o todos los necesarios escribiendo en el terminal: $sudo /usr/bin/perl install-module./checksetup.pl ?all Para comprobar que tenemos todos los m´dulos necesarios instalados escribe o de nuevo en el terminal: $sudo . o Los instalamos escribiendo en el terminal: $sudo apt-get install libapache2-mod-perl2 libapache2-mod-perl2-dev libapache2-mod-perl2-doc $ sudo /usr/bin/perl install-module.pl ?check-modules Si alguno de los m´dulos necesarios no se ha instalado escribe de nuevo en o un terminal: $sudo /usr/bin/perl install-module. escribe o en el terminal: $sudo . entre otras cosas. Para crear a esta base de datos utilizaremos el cliente de MySQL que ya hemos instalado. Edita este fichero y modifica las siguiente variables de Bugzilla: $webservergroup = ?www-data?. 1 row affected (0. se habr´ creado el fichero localconfig en el a directorio /var/www/bugzilla-4.

192CAP´ ITULO 13. CONTROL DE ERRORES CON MYLYN Y BUGZILLA mysql> show databases; +-----------+ | Database | +-----------+ | information_schema | | bugs | | mysql | +-----------+ 3 rows in set (0.00 sec) Ver´s que efectivamente tenemos la base de datos llamada bugs creada. Lo a siguiente es asignar todos los privilegios para trabajar con esta base de datos al administrador root, para ello escribe: mysql> GRANT ALL PRIVILEGES ON bugs.* TO root@localhost IDENTIFIED BY ?clave de administrador?; mysql> FLUSH PRIVILEGES; Para salir del cliente de MySQL escribe: mysql> quit; De regreso al terminal vamos a continuar con la instalaci´n de Bugzilla, o escribe lo siguiente en el terminal: $ ./checksetup.pl Este script de perl crear´, entre otras cosas, todas las tablas necesarias en a la base de datos bugs y configurar´ Bugzilla. Tambi´n se nos pedir´ que introa e a duzcamos el correo electr´nico y clave de acceso del Administrador de Bugzilla. o El nombre de usuario en Bugzilla debe ser un correo electr´nico. o El siguiente paso es configurar Apache para que reconozca el directorio donde tenemos instalado Bugzilla, para ello sit´ate en el directorio /etc/apache22 y u edita el fichero httpd.conf y escribe en ´l lo siguiente: e Alias /bugzilla "/var/www/bugzilla-4.0" <Directory /var/www/bugzilla-4.0> AddHandler cgi-script .cgi Options +Indexes +ExecCGI DirectoryIndex index.cgi AllowOverride Limit </Directory> En este punto s´lo nos queda reiniciar el servidor web Apache escribiendo lo o siguiente en el terminal: $sudo /etc/init.d/apache2 restart Y si no tenemos ning´n problema ya podemos abrir un navegador web para u conectarnos a Bugzilla escribiendo como url la siguiente http://localhost/

´ 13.2. SISTEMA DE GESTION DE ERRORES BUGZILLA

193

Figura 13.11: P´gina de inicio de Bugzilla. a

Figura 13.12: P´gina de introducci´n de usuario y clave de Bugzilla. a o bugzilla. Deberemos ver la p´gina de inicio de Bugzilla tal y como se muestra a en la siguiente Figura 13.11: Una vez ingresado en Bugzilla utilizando el correo electr´nico del administrao dor como usuario y la clave que hemos definido en la instalaci´n de de Bugzilla, o se presentar´ una pantalla como la mostrada en la Figura 13.12, seleccionamos a el enlace Administration para acabar de configurar Bugzilla. En la nueva pantalla mostrada en la Figura 13.13 seleccionamos el enlace Parameters lo que nos dar´ paso a la pantalla mostrada en la Figura 13.14 a En esta pantalla, los unicos par´metros que es necesario configurar son ´ a urlbase y cookiepath. Como valor de urlbas escribiremos la url de nuestro servidor, en el ejemplo se muestra http://localhost/bugzilla/ lo que indica que estamos utilizando Bugzilla en el servidor local, no tendremos acceso a este servidor desde otra m´quina. Si Bugzilla estuviese instalado en a
2 El directorio donde se encuentra el fichero httpd.conf puede ser distinto dependiendo de la distribuci´n de Linux o del sistema operativo. o

194CAP´ ITULO 13. CONTROL DE ERRORES CON MYLYN Y BUGZILLA

Figura 13.13: P´gina de administraci´n de Bugzilla. a o

Figura 13.14: P´gina de definici´n de par´metros de Bugzilla. a o a

´ 13.2. SISTEMA DE GESTION DE ERRORES BUGZILLA

195

Figura 13.15: Lista de usuarios en Bugzilla. un servidor con nombre mi.servidor.com el valor del par´metro urlbase ser´ a ıa http://mi.servidor.com/bugzilla/. Como valor de cookiepath escribiremos /bugzilla/. Finalmente pulsamos el bot´n Sava changes. o

13.2.3.

Trabajar con Bugzilla

Como ya se hemos comentado, Bugzilla es un sistema de gesti´n de errores con o interfaz web. El n´cleo de trabajo con Bugzilla es el proyecto. En Bugzilla se u pueden crear tantos proyectos como sea necesario. Una vez creado un proyecto, todos los usuarios que est´n autorizados a dar de alta los errores encontrados e en el proyecto pueden empezara a hacerlo. Por lo tanto, lo primero que vamos a hacer es crear un nuevo proyecto. Despu´s crearemos un usuario y le asignaremos privilegios para dar de alta los e errores encontrados en el proyecto reci´n creado. e Todo este proceso lo vamos a hacer con la cuenta de Administrador de Bugzilla. Ingresa en Bugzilla pulsando sobre el enlace Log In que se muestra en la Figura 13.11, se te solicitar´ un nombre de usuario y su clave de acceso. Como a ya hemos comentado, los nombre de usuario en Bugzilla deben ser direcciones de correo electr´nico, debemos introducir la direcci´n de correo electr´nico de o o o Administrador que introdujimos en la configuraci´n de Bugzilla y su clave. o Como en el caso de la configuraci´n de los par´metros de Bugzilla, seleccionao a mos en enlace Administration y esta vez, dentro de esta pantalla, seleccionamos el enlace Users, lo que nos dar´ paso a la pantalla mostrada en la Figura 13.15, a donde seleccionamos el enlace add a new user, se nos mostrar´ la pantalla de a la Figura 13.16 donde introduciremos los datos del nuevo usuario. F´ ıjate que como nombre de usuario se debe introducir una direcci´n de correo electr´nico. o o Finalmente pulsamos el bot´n Add. o Lo siguiente que vamos a hacer es crear un nuevo producto. Como ya se ha comentado, los errores se dan de alta en un determinado producto, puedes pensar que los productos son tus proyectos. Para crear un nuevo producto, vuelve a la p´gina Administration y selecciona el enlace Products, ver´s una p´gina como a a a la de la Figura 13.17, por defecto hay un producto de prueba creado, llamado TestProduct. Vamos a a˜adir un nuevo producto selecciona el enlace Add lo n que te llevar´ a la nueva p´gina mostrada en la Figura 13.18, introduce los a a par´metros del nuevo producto y pulsa el bot´n Add, esto te llevar´ a la nueva a o a p´gina mostrada en la Figura 13.19, en esta p´gina se nos indica que debemos a a crear al menos un componente dentro del nuevo producto, puedes pensar que los componentes de los productos son como las tareas de tu proyecto. Selecciona

196CAP´ ITULO 13. CONTROL DE ERRORES CON MYLYN Y BUGZILLA

Figura 13.16: P´gina de creaci´n de un nuevo usuario en Bugzilla. a o

Figura 13.17: Lista de productos de Bugzilla. el enlace Edit components, lo que te llevar´ a la p´gina mostrada en la Figura a a 13.20. Selecciona el enlace Add con lo que te llevar´ a la p´gina de definici´n a a o del nuevo componente mostrada en la Figura 13.21, introduce en ella los datos del nuevo componente y pulsa el bot´n Add lo que te dar´ entrada de nuevo a o a la p´gina donde se muestra los componentes de un producto. Ahora ver´s que a a el componente ComponentePrueba se ha a˜adido a la lista. n Resumiendo lo que he hemos hecho hasta este momento: 1. Hemos configurado Bugzilla. 2. Hemos creado un nuevo usuario.

Figura 13.18: Propiedades de un producto en Bugzilla.

Debemos crear al menos un e componente en este producto.21: Propiedades de un nuevo componente en Bugzilla.19: Producto reci´n creado en Bugzilla.2. Figura 13. . Figura 13.20: Lista de los componentes de un producto en Bugzilla. SISTEMA DE GESTION DE ERRORES BUGZILLA 197 Figura 13.´ 13.

Figura 13. n Ahora ya podemos ingresar a Bugzilla con nuestro nuevo usuario y dar de alta un error en el componente reci´n creado. 3. a Para completar esta breve introducci´n al uso de Bugzilla realicemos una o b´squeda sobre la base de datos de errores. seleccionamos el enlace NuevoProducto. En esta p´gina seleccionemos el producto a a a . toda n o ella aparecer´ en esta pantalla.22 donde seleccionar´s el producto donde quieres dar de alta el error. a En nuestro caso. y en la nueva p´gina seleccionemos el enlace Advanced Search. en este momento se nos mosa trar´ la p´gina de la Figura 13. lo que nos llevar´ a a la p´gina mostrada en la Figura 13.198CAP´ ITULO 13. e ´ y a medida que trabajemos sobre este error y a˜adamos nueva informaci´n. En la p´gina de inicio de Bugzilla selecciona el e a icono con leyenda File a Bug. Para ello sal de Bugzilla ya que e hemos ingresado como administradores. CONTROL DE ERRORES CON MYLYN Y BUGZILLA Figura 13.22: Lista de los productos en Bugzilla en los que podemos dar de alta nuevos errores.23 y pulsa el bot´n Submit Bug. Hemos a˜adido un nuevo componente (tarea) al producto (proyecto). lo que te llevar´ a la nueva p´gina mostrada en la a a Figura 13.24 donde se muestran todos los a a detalles del error reci´n creado. Para ello vuelve a la p´gina inicial u a de Bugzilla y selecciona el icono que tiene como leyenda Search. lo que te a o dar´ paso a la p´gina mostrada en la Figura 13.25. Esta ultima contiene todos los detalles del error. Hemos creado un nuevo producto (proyecto). 4.23: Definici´n de los par´metros del error que se est´ dando de alta o a a en Bugzilla. e ingresa de nuevo pero esta vez con el usuario y clave reci´n creados.

algunas de nuestras tareas consisten en solucionar errores en las aplicaciones que desarrollamos. Acceso a Bugzilla desde MyLyn y Eclipse Tanto MyLyn como Bugzilla son herramientas muy utiles en el desarrollo de ´ software utilizadas de modo independiente. pero sin duda.24: Informaci´n sobre el error reci´n creado en Bugzilla. esta consulta se a interpreta como ((Busca todos los errores dados de alta en el producto NuevoProducto)). Como desarrolladores de software. e Hasta aqu´ hemos visto el trabajo b´sico con Bugzilla como una potent´ ı a ısima herramienta de control y gesti´n de errores.26 o a a con los resultados de la b´squeda.3. S´lo aparece un unico error y al pulsar sobre u o ´ el identificador de este error volveremos a la p´gina de informaci´n detallada a o sobre ´l. o e NuevoProducto y dejemos el resto de campos tal y como est´n. o 13. Bugzilla es o ´ o un potente sistema de seguimiento de errores. la potencia de esta o herramienta se magnifica en combinaci´n con MyLyn. la posibilidad de combinar ambas soluciones en Eclipse nos facilita enormemente el desarrollo de software y el seguimiento de errores. tal y como se muestra en o la siguiente secci´n. Pero sin duda. Hemos visto c´mo MyLyn nos permite definir tareas y concentrar nuestra o atenci´n unicamente en el c´digo relacionado con ellas.13. ACCESO A BUGZILLA DESDE MYLYN Y ECLIPSE 199 Figura 13. pulsa el bot´n Search y ver´ la p´gina mostrada en la Figura 13. Por otro lado.3. podemos ver la resoluci´n de cada error como una tarea o espec´ ıfica. Ser´ muy interesante poder combinar la potencia de MyLyn con la ıa de Bugzilla para trabajar en la resoluci´n de errores como si se tratase de otra o .

26: Resultado de la b´squeda de errores en Bugzilla. u .200CAP´ ITULO 13. CONTROL DE ERRORES CON MYLYN Y BUGZILLA Figura 13. u Figura 13.25: B´squeda de errores en Bugzilla.

o . es crear un repositorio hacia Bugzilla. 13.3.3. Lo que vamos a hacer esta vez.org/mylyn/new/ para conocer los detalles.2. Rell´nala con los datos de un error e tal y como muestra la Figura 13. o Si la conexi´n se establece podemos pulsar el bot´n Finish. 13. introduce los datos de conexi´n al repoa o sitorio de Bugzilla como se muestra en la Figura 13. Como ejercicio puedes probar a buscar el nuevo error desde un navegador web en Bugzilla. Recuperar errores desde Bugzilla como tareas en MyLyn Por ultimo. Otra ventaja importante es que podemos trabajar con Bugzilla directamente desde Eclipse sin necesidad de abandonar el entorno de desarrollo para realizar el seguimiento de los errores. o o 3 Es posible que tengas que actualizar MyLyn para trabajar con la versi´n 4. veamos c´mo podemos crear una consulta desde MyLyn para que nos ´ o aparezcan como tareas en la vista Task List los errores presentes en el repositorio de Bugzilla. Para ello seleccionemos el bot´n New Query que se muestra en la o Figura 13.3.29 donde aparecer´ el repositorio reci´n creado Errores.2.0 de Bugzilla. o En la nueva ventana que se abrir´. selecciona Bugzilla y pulsa el bot´n Next 3 .4 pulsa esta vez sobre el bot´n Add Task o Repository.28.3. o consulta la direcci´n http://www.2. y pulsemos el bot´n Next.13.3 y en la ventana que se abrir´ seleccionemos el repositorio creado en a la secci´n anterior Errores.2.3. a e Pulsa de nuevo el bot´n Finish con lo que se abrir´ una solapa en Eclipse o a para definir las propiedades del nuevo error. A˜ adir errores a Bugzilla desde Eclipse n Para crear un nuevo error en Bugzilla desde Eclipse crea una nueva tarea en la vista Task List tal y como se muestra en la Figura 13.1. Beneficios de la combinaci´n de Bugzilla y MyLyn o desde Eclipse La principal ventaja de poder trabajar en Eclipse con Bugzilla a trav´s de e MyLyn es que podemos realizar el seguimiento de los errores como si de otra tarea cualquiera se tratase.27. ver´s la ventana o o a de la Figura 13. de lo contrario. 13.eclipse. Al pulsar sobre el bot´n Add Task Repository se abrir´ la ventana mostrada en o a la Figura 13.3.30. Finalmente pulsa el bot´n Submit con lo que se enviar´ el nuevo error al o a repositorio Bugzilla. 201 13. ACCESO A BUGZILLA DESDE MYLYN Y ECLIPSE tarea cualquiera. Una vez rellenados los datos de conexi´n es util pulsar el bot´n Validate o ´ o Settings para comprobar que se puede establecer la conexi´n con el repositorio. Cuando se abra la ventana mostrada en la Figura 13. Trabajo con MyLyn y Bugzilla desde Eclipse En esta secci´n vamos a presentar los fundamentos del trabajo conjunto desde o Eclipse con MyLyn y Bugzilla. En MyLyn podemos definir una consulta ha Bugzilla de tal modo que al dar de alta un nuevo error este nos aparezca como una nueva tarea en MyLyn. o o corrige los datos de conexi´n y vuelve a pulsar el bot´n Finish.1.

202CAP´ ITULO 13. o Figura 13.28: Datos del repositorio Bugzilla.27: Creaci´n de un nuevo repositorio en MyLyn. CONTROL DE ERRORES CON MYLYN Y BUGZILLA Figura 13. .

tal a y como se muestra en la Figura 13.eclipse. muy aconsejables de ver.org/index. y pulsemos el bot´n Next. La opci´n que nos interesa es la primera. adem´s a a de disponer de todos los campos que ofrece el conector a Bugzilla. . El cap´ ıtulo 25 de la referencia [13] est´ dedicado enteramente a MyLyn.3. e En la nueva ventana que se abrir´ tenemos dos opciones: a Create query using form. Ahora podr´s trabajar con ellos como con cualquier otra tarea local. ACCESO A BUGZILLA DESDE MYLYN Y ECLIPSE 203 Figura 13.32.13.php/Mylyn/User_Guide o se puede encontrar un manual en l´ ınea completo para el trabajo con MyLyn.eclipse. Lecturas recomendadas.org/mylyn/start/ se pueo den encontrar otros enlaces de gran inter´s como v´ e ıdeo tutoriales sobre MyLyn. que aparece seleccionada por deo fecto.31. y finalmente pulsa el bot´n Finish. a En la direcci´n http://wiki. Create query from existing URL. En la direcci´n http://www. o En la nueva ventana que se abrir´ introduce los par´metros de la consulta a a tal y como muestra la Figura 13.29: Repositorio Errores reci´n creado. en la o vista Task List podr´s ver los errores importados a MyLyn desde Bugzilla.

El cap´ ıtulo 27 de la referencia [13] est´ dedicado enteramente a Bugzilla a La direcci´n web de Bugzilla es http://www. all´ podr´s o ı a encontrar gran cantidad de informaci´n sobre esta herramienta.30: Datos del repositorio Bugzilla. CONTROL DE ERRORES CON MYLYN Y BUGZILLA Figura 13.204CAP´ ITULO 13.bugzilla. o .org/.

32: Datos del repositorio Bugzilla.13. Figura 13.3. . ACCESO A BUGZILLA DESDE MYLYN Y ECLIPSE 205 Figura 13.31: Datos del repositorio Bugzilla.

206CAP´ ITULO 13. CONTROL DE ERRORES CON MYLYN Y BUGZILLA .

o 14. Ciclo de vida de un hilo . . . . . . el interfaz gr´fico se quedar´ congelado cuando el usuario inicie o a a el c´lculo. . . . . 14. ninguna aplicaci´n se comporta as´ o al menos no deber´ a o ı. .2. Sincronizac´n utilizando los cerrojos intr´ o ınsecos . 14. Si tu aplicaci´n tiene un unico Hilo a o ´ de ejecuci´n. o 14. .4. o con un interfaz gr´fico en la que al pulsar un bot´n se lleva a cabo un complejo a o c´lculo que consume mucho tiempo de CPU. los Hilos son nativos en Java. . . . . .5. . o 14. . . . ya que hasta que este no se acabe. . .2. . Control de hilos . . Creaci´n de hilos en Java . Imagina que has escrito una aplicaci´n. . . . o 14. .3. no volver´ el control al interfaz a a gr´fico. . . . .2. . . ıa. . . . o 208 209 209 210 211 212 213 215 215 218 Introducci´n o La programaci´n concurrente es nativa en Java. .1. . . o 14. . Un buen entendimiento de c´mo trabajar con Hilos es fundamental cuando o en nuestras aplicaciones se ejecutan m´s de una tarea de manera concurrente. .5. . 14. . . . . . . . a Y precisamente las aplicaciones con interfaces gr´ficos son un excelente ejemplo a de las ventajas de trabajar con Hilos. . . Consideraciones soe bre el uso de hilos . . . . . .Cap´ ıtulo 14 Programaci´n concurrente o con Hilos Contenidos 14. Creaci´n de un Hilo mediante una clase interna o an´nima .1. 14. .2. Obviamente. . . . . .1. .3. . . . . esto quiere decir que no necesio tamos ninguna biblioteca adicional para poder trabajar con Hilos. . ¿Qu´ es un hilo? Utilidades. . . Creaci´n de un Hilo extendiendo a la clase Thread . . . . . . . . . .2. Sincronizaci´n utilizando el interface Lock . . . Todos los Hilos de una aplicaci´n en Java comparten el mismo espacio de o 207 . . . . . . Sincronizaci´n . . . . . . Creaci´n de un Hilo mediante una clase interna . . . . . . .2.5. . . . . . . . . . . . . . . . . .

Consideracioe nes sobre el uso de hilos De un modo muy resumido podemos decir que un Hilo es un flujo de control independiente dentro de un programa. como empieza a ser la habitual. puede no ser el deseado. vas a conocer o c´mo se crean Hilos en Java y como sincronizar su ejecuci´n cuando acceden a o o recursos compartidos para que no haya inconsistencias en tus aplicaciones. se cede el disfrute de la CPU al segundo hilo. a a Evidentemente se ha producido un error ya que en este caso el acceso al recurso compartido suma no est´ sincronizado. De alg´n modo hay que establecer un mecanismo de sincronizaci´n u o para que el acceso a zonas de memoria compartida no den lugar a este tipo de comportamiento err´neo. por lo que incrementa en dos unidades la variable cantidad que pasa a valer 11. el resultado. p r i n t l n ( " C a n t i d a d : " + c a n t i d a d ) .208 ´ CAP´ ITULO 14.1. y antes de que se ejecute la segunda l´ ınea. ¿Qu´ es un hilo? Utilidades. Listado 14. o . y despu´s de modificar el e valor de cantidad. o En este cap´ ıtulo vas a conocer c´mo trabajar con Hilos en Java. la condici´n que comprob´ el primer Hilo ya no es v´lida y a´n o o a u as´ se incrementar´ el valor de la variable suma que de 11 pasar´ a valer 12. de nuevo. ya que si varios Hilos intentan acceder al mismo recurso compartido y al mismo tiempo. Para ver lo que queremos decir a con claridad. Como tal tiene su propia pila de llamadas. lo que implica que comparten todas las instancias del programa excepto las locales. si el acceso no est´ sincronizado. pero todos los Hilos creados en el mismo programa comparten el mismo espacio de direcciones. En este caso se pueden producir colisiones e inconsistencias por el uso compartido de memoria. A cambio tenemos que pagar un precio. la condici´n de la l´ o ınea 1 se cumple. varios hilos pueden estar a u ejecut´ndose de modo paralelo en cada uno de los n´cleos de la CPU. se cede el disfrute de la CPU al primer hilo. con lo que la programaci´n de soluciones complejas.1: C´digo que ejecuta el primer Hilo. supongamos dos hilos que se est´n ejecutando sobre una unica a ´ CPU. ya que si disponemos.1 y el o que ejecuta el segundo aparece en el Listado 14. En este momento. Supongamos que el primer Hilo tiene el disfrute de la unica CPU. a u Tambi´n podemos pensar que cada uno de los Hilos es un programa secuene cial en s´ mismo. a 1 2 3 i f ( cantidad < 10) c a n t i d a d ++. y que el valor de la variable cantidad ´ en ese momento es 9. de CPUs con m´s de un n´cleo. se simplifican enormemente al ser divididas en partes que se ejecutan de modo independiente pero coordinado. el c´digo que ejecuta el primero de ellos aparece en el Listado 14. 14. a Esto proporciona grandes ventajas.2. que comprueba que la condici´n de su l´ o ınea 1 se cumple. lo que implica que varios Hilos pueden estar accediendo a la misma zona de memoria (por ejemplo una variable) para modificar su valor. PROGRAMACION CONCURRENTE CON HILOS memoria. cuando ı o se piensan como un todo. o u t . Nuestros programas pueden tener un gran n´mero de Hilos u ejecut´ndose al mismo tiempo y todos ellos comparten el uso de la CPU. ı. System .

Necesitamos o a dos ingredientes. 14.1: La idea de c´mo crear un Hilo en Java gr´ficamente. luego simplemente extendi´ndola y sobrescribiendo su m´todo public void run() tendremos un nuevo e e Hilo. Creaci´n de hilos en Java o Lo primero que hay que conocer de la creaci´n de Hilos en Java es que se o componen de dos partes. a La clase que representa una tarea. Definir una clase interna an´nima que implemente el interface Runnable. Definir una clase interna que implemente el interface Runnable.1. y cuales son sus ventajas e y desventajas. Por otro lado. ha de implemena tar el interface Runnable. La Figura 14.1 muestra gr´ficamente este concepto. el controlador del Hilo ser´ una instancia a de la clase Thread. a Podemos utilizar tres t´cnicas distintas para crear un hilo en Java: e 1. Extender a la clase Thread. F´ e ıjate que al crear . y que controlar´ un Hilo.2. Creaci´n de un Hilo extendiendo a la clase Thread o La clase Thread implementa la interface Runnable. por un lado definiremos la tarea que queremos que se ejecute de manera concurrente con otras tareas. El Listado 14. Este interface declara un unico m´todo public ´ e void run().´ 14. Listado 14. o Veamos cada una de estas t´cnicas por separado. 1 2 3 i f ( cantidad < 20) c a n t i d a d += 2 . System . el c´digo del cual se ejecutar´ de manera concurrente con otros o a Hilos cuando se inicie.2: C´digo que ejecuta el segundo Hilo. que nos permitir´ sincronizarla con el resto de tareas. o 14. y el o controlador del hilo (clase Thread). p r i n t l n ( " C a n t i d a d : " + c a n t i d a d ) .2. 3.3 muestra el uso de esta primera t´cnica. a quien en el momento de su creaci´n debemos pasarle como o argumento una instancia de la clase que implementa el interface Runnable.2. CREACION DE HILOS EN JAVA 209 Figura 14. o u t . 2. la tarea cuyo c´digo se va a ejecutar concurrentemente. y por otro lado tenemos el controlador de esa tarea.

2. para indicar que el Hilo debe empezar a o ejecutarse debemos llamar a su m´todo start.3: Creaci´n de un Hilo extendiendo a la clase Thread o F´ ıjate que el m´todo public void run() es un m´todo p´blico. Por ello. public f i n a l c l a s s H i l o C l a s e I n t e r n a { private H i l o C l a s e I n t e r n a ( ) { super ( ) . o u t .4 muestra un ejemplo de esta segunda t´cnica. esta t´cnica de creaci´n de Hilos est´ desaconsejada. el Hilo permanecer´ vivo siempre que se encuentre a ejecutando su m´todo run(). s t a r t ( ) . este no empieza su ejecuci´n. o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package h i l o s . i < 1 0 . s t a r t ( ) . miene e u tras el Hilo se est´ ejecutando. El Hilo permanece vivo sieme pre que se est´ ejecutando su m´todo public void run(). public f i n a l c l a s s ThreadExtendido extends Thread { public ThreadExtendido ( ) { super ( ) . PROGRAMACION CONCURRENTE CON HILOS el Hilo. o u t . e 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package h i l o s . Creaci´n de un Hilo mediante una clase interna o El Listado 14. i ++) System . o e o a 14. } } private void e j e c u t a ( ) { new Thread (new C l a s e I n t e r n a ( ) ) . dentro de la clase HiloClaseInterna. } public void run ( ) { f o r ( i n t i = 0 . El resultado de la e e ejecuci´n de este Hilo es que se muestran 10 mensajes de texto por consola. cualquier otra clase podr´ llamar al m´todo a ıa e run() de esta clase. i < 1 0 . p r i n t l n ( " E s t a m o s e n : " + i ) .2. Y en la l´ ınea 20 creamos una instancia de la clase Thread con un argumento que es una instancia de la clase ClaseInterna que define en su m´todo public void run() la tarea que se ejecuta concurrentemente. Hemos definido la e clase ClaseInterna que implementa el interface Runnable. } private c l a s s C l a s e I n t e r n a implements Runnable { private C l a s e I n t e r n a ( ) { super ( ) . } } args ) { Listado 14. } public s t a t i c void main ( S t r i n g [ ] new ThreadExtendido ( ) . Igual e que en el ejemplo anterior. } public s t a t i c void main ( S t r i n g [ ] args ) { . i ++) System . luego. p r i n t l n ( " E s t a m o s e n : " + i ) .210 ´ CAP´ ITULO 14. provocando con ello inconsistencias durante la ejecuci´n de o nuestra aplicaci´n. } @Override public void run ( ) { f o r ( i n t i = 0 .

y la clase interna implementa el algoritmo de ejecuci´n de la tarea.5 muestra un ejemplo del uso de clases internas an´nimas para o la creaci´n de Hilos. Creaci´n de un Hilo mediante una clase interna o an´nima o El Listado 14. e j e c u t a ( ) . Este t´cnica es muy parecida a la t´cnica de la secci´n o e e o anterior salvo que se ha utilizado una clase interna an´nima para implementar o la tarea que se ejecuta de manera concurrente. e j e c u t a ( ) . } private void e j e c u t a ( ) { new Thread (new Runnable ( ) { @Override public void run ( ) { f o r ( i n t i = 0 . s t a r t ( ) . o . o en este caso la clase interna ClaseInterna es private.3. CREACION DE HILOS EN JAVA 24 25 26 211 new H i l o C l a s e I n t e r n a ( ) . public f i n a l c l a s s H i l o C l a s e I n t e r n a A n o n i m a { private H i l o C l a s e I n t e r n a A n o n i m a ( ) { super ( ) . 14. i ++) System . o u t . p r i n t l n ( " E s t a m o s e n : " + i ) . luego s´lo se podr´ acceo a der a su m´todo publi void run() desde dentro de la clase en la que est´ dee a finida.´ 14. } }) . } public s t a t i c void main ( S t r i n g [ ] a r g s ) { new H i l o C l a s e I n t e r n a A n o n i m a ( ) .4: Creaci´n de un Hilo como una clase interna que implementa el o interface Runnable Al contrario que en la creaci´n de hilos como extensiones de la clase Thread.2. o Este m´todo est´ recomendado cuando la tarea que se debe ejecutar de e a manera concurrente es compleja. } } Listado 14. podremos crear instancias de esta clase en cualquier otro lugar de la clase que la contiene. i < 1 0 . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package h i l o s .2. hemos evitado que otra clase llame de modo accidental al m´todo run() e previniendo con ello inconsistencias en nuestra aplicaci´n.5: Creaci´n de un Hilo como una clase interna an´nima que o o implementa el interface Runnable Esta t´cnica est´ recomendada cuando el c´digo de la tarea concurrente es e a o s´lo de algunas l´ o ıneas y no se va a reutilizar en ning´n otro caso. ya que al ser u una clase an´nima no tienen nombre y no podr´ o ıamos crear una instancia de una clase sin nombre en ninguna otra parte de nuestro c´digo. ya que la tarea concurrente est´ implementada o a a dentro de una clase. } } Listado 14. Adem´s.

Sale de su m´todo public void run(). o La diferencia entre los estados Pausado o Planificado es que de un estado Planificado conocemos el momento en que de nuevo pasar´ a Ejecuci´n. un Hilo puede pasar al estado Pausado o al estado Planificado. Un Hilo puede pasar al estado Terminado desde el estado en Ejecuo ci´n. o Un hilo pasa al estado Terminado cuando ocurre alguna de estas tres cosas: 1.2: Estados en los que se puede encontrar un Hilo y las posibles transiciones entre ellos. en este o estado el Hilo no se ejecuta. Para acabar un Hilo limpiamente se aconseja salir de su m´todo run(). Dependiena o do del m´todo de la clase Thread que utilicemos.2 muestra los estados en los que se o a puede encontrar un hilo y las transiciones entre los estados. La Figura 14. Durante su ejea o cuci´n. se dice que el Hilo se ha terminado. Se produce una excepci´n dentro del m´todo run() no gestionada. cuando se a ha iterado un cierto n´mero de veces. pero siempre podr´ pasar de nuevo al estado en a Ejecuci´n. Se llama al m´todo public void stop() del Hilo. PROGRAMACION CONCURRENTE CON HILOS Figura 14. Ciclo de vida de un hilo Los Hilos pueden encontrarse en m´s estados que unicamente en el estado de a ´ ejecuci´n cuando est´n vivos. y en este momento se dice que est´ en Ejecuci´n. De un a o estado Pausado no sabemos cuando volver´ al estado Ejecuci´n. 14.3. Un hilo inicia su ejecuci´n cuando se llama a su m´todo public void o e start(). o e 3. Pausado o Planificado. e 2. e Esta buena pr´ctica es la que se sigue en los ejemplo mostrados. u e . e Buena pr´ctica a El uso del m´todo stop() para detener la ejecuci´n de un Hilo est´ fuertemente e o a desaconsejado ya que puede provocar inconsistencias y de hecho est´ marcado a como obsoleto en el API Java.212 ´ CAP´ ITULO 14. se sale del m´todo public void run(). y un hilo Terminado nunca m´s puede o a pasar de nuevo al estado en Ejecuci´n. podremos llevar un Hilo en e Ejecuci´n a uno de estos estados.

printStackTrace () . } } args ) { Listado 14. con el a o m´todo sleep(long milisegundos) planificamos que el Hilo vuelva a su estae do Ejecuci´n pasados los milisegundos especificados. } public s t a t i c void main ( S t r i n g [ ] new E j e m p l o S l e e p ( ) . Este m´todo lanza una excepci´n e e o de tipo InterruptedException. Control de hilos El control de hilos se puede llevar a cabo desde una perspectiva gruesa tratando cada Hilo como un bloque.14. s l e e p ( 1 0 0 0 ) . cada segundo. s t a r t ( ) . El m´todo sleep(long) puede lanzar una e excepci´n de tipo InterruptedException que debemos gestionar. o El Listado 14. } } catch ( I n t e r r u p t e d E x c e p t i o n e ) { e . Thread . i ++) { System . el Hilo volver´ al estado en Ejecuci´n. i < 1 0 . o u t . o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package h i l o s . e j e c u t a ( ) . } } }) . a Podemos suspender temporalmente la ejecuci´n de un Hilo mediante el o uso del m´todo public static void sleep(long milisegundos)1 . int nanosegundos . public f i n a l c l a s s E j e m p l o S l e e p { private E j e m p l o S l e e p ( ) { super ( ) . p r i n t l n ( " E s t a m o s e n : " + i ) . 14.6 muestra un ejemplo que muestra un mensaje cada 1000 milisegundos. o desde una perspectiva m´s fina mediante el uso de a la sincronizaci´n. Es decir. CONTROL DE HILOS 213 Otra t´cnica muy extendida es utilizar dentro del m´todo public void run() e e un bucle while(condicion) cuya condici´n inicialmente es true y se cambia a o false cuando se quiere acabar el Hilo limpiamente.4. Piensa por ejemplo en un Hilo que cuenta el n´mero e u 1 Tambi´n existe una versi´n de mayor precisi´n public static void sleep(long e o o milisegundos. es decir. En esta secci´n veremos como coordinar la ejecuci´n de Hilos o o o desde una perspectiva gruesa dejando para la siguiente secci´n la sincronizaci´n o o de Hilos desde una perspectiva m´s fina. Existen casos en los que un Hilo debe esperar a que otro acabe su ejecuci´n o para que ´l pueda continuar. Pasado el e tiempo especificado.6: Uso del m´todo sleep(long milisegundos) para pausar la e ejecuci´n del Hilo durante el intervalo de tiempo espedificado. } private void e j e c u t a ( ) { new Thread (new Runnable ( ) { @Override public void run ( ) { try { f o r ( i n t i = 0 .4. o Si un Hilo est´ en estado Pausado o Planificado siempre lo podremos sacar de a este estado con el m´todo void interrupt().

7: Uso del m´todo join() para pausar la ejecuci´n del Hilo hasta e o que acabe la ejecuci´n de otro. start () . i < 5 . Para que un Hilo espere a que otro acabe su ejecuci´n llamaremos al m´todo o e public final void join()2 del segundo Hilo en el c´digo del primero. PROGRAMACION CONCURRENTE CON HILOS de caracteres que se leen desde un fichero. private E j e m p l o J o i n ( ) { super ( ) . printStackTrace () . int nanosegundos en los que se espera. i ++) { System . como m´ximo. } } } private c l a s s TareaQueEspera implements Runnable { public void run ( ) { try { f o r ( i n t i = 0 . } } catch ( I n t e r r u p t e d E x c e p t i o n e ) { e . join () . o u t . p r i n t l n ( " C u e n t a y e s p e r a : " + i ) . s t a r t ( ) . printStackTrace () . s l e e p ( 5 0 0 ) .7. s l e e p ( 5 0 0 ) . i < 1 0 . tal y o como muestra el ejemplo del Listado 14. o u t . s l e e p ( 5 0 0 ) . hilo . } private void e j e c u t a ( ) { h i l o = new Thread (new Tarea ( ) ) . i < 1 0 . new Thread (new TareaQueEspera ( ) ) . } } catch ( I n t e r r u p t e d E x c e p t i o n e ) { e . f o r ( i n t i = 5 . i ++) { System . o 2 Existen dos versiones de este m´todo public final void join(long milisegundo y e public final void sleep(long milisegundos. } } args ) { Listado 14. } hilo . el tiempo especificado a . i ++) { System . el Hilo que cuenta el n´mero u u de caracteres debe esperar a que el Hilo que carga el fichero acabe su tarea antes de empezar con la cuenta. public f i n a l c l a s s E j e m p l o J o i n { private Thread h i l o .214 ´ CAP´ ITULO 14. Si la lectura del fichero se hace en un Hilo y la cuenta del n´mero de caracteres en otro. } } } public s t a t i c void main ( S t r i n g [ ] new E j e m p l o J o i n ( ) . Thread . Thread . o u t . } private c l a s s Tarea implements Runnable { public void run ( ) { try { f o r ( i n t i = 0 . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 package h i l o s . Thread . e j e c u t a ( ) . p r i n t l n ( " C u e n t a : " + i ) . p r i n t l n ( " S a l g o d e l a e s p e r a y c u e n t a : " + i ) .

. si el cerrojo no est´ en posesi´n de ning´n otro Hilo lo adquirir´.8 es relativa a todo el objeto. o En las secciones siguientes vamos a ver c´mo sincronizar el acceso a recursos o compartidos con dos t´cnicas: mediante el uso de cerrojos intr´ e ınsecos y mediante la interface Lock y la interface Condition introducidas ambas en la versi´n o 5. si un Hilo est´ en posesi´n del cerrojo a o . El cerrojo a intr´ ınseco pertenece al objeto y sincroniza el acceso a todos los m´todos definidos e como synchronized. Una vez en posesi´n a o del cerrojo puede trabajar con el recurso compartido con la seguridad de que ning´n otro Hilo acceder´ a este recurso hasta que ´l no libere el cerrojo que u a e indica la propiedad de uso del recurso. el Hilo que a o intenta adquirir el cerrojo tendr´ que esperar a que el otro lo libere. Como ya sabemos. y otro Hilo intenta acceder al metodo2() no podr´ hacerlo ya que no podr´ adquirir el cerrojo intr´ a a ınseco del objeto.8: Para indica que el acceso a un m´todo est´ sincronizado utilizamos e a la palabra reservada synchronized. si un Hilo adquiere el cerrojo intr´ ınseco accediendo al metodo1() del ejemplo anterior. Sincronizaci´n o En los ejemplos anteriores el control sobre Hilos no implicaba acceso concurrente a recursos.´ 14. SINCRONIZACION 215 14. 14. Un Hilo libera el cerrojo cuando acaba la ejecuci´n del m´todo sincronizado. de a o u a lo contrario tendr´ que esperar a que el cerrojo se libere. } Listado 14.. y en o e ese momento cualquier otro Hilo que se encuentre a la espera podr´ adquirir el a cerrojo.5.1. Definir un m´todo como synchronized implica que antes de que un Hilo e pueda ejecutar el m´todo. Si el cerrojo intr´ ınseco est´ en posesi´n de otro Hilo. Antes de acceder al recurso compartido un Hilo intentar´ adquirir un a cerrojo. debe adquirir el cerrojo intr´ e ınseco del objeto para poder ejecutarlo. Todo objeto tiene un cerrojo intr´ ınseco. como en el Listado 14. Cuando varios Hilos que se ejecutan de modo concurrente intentan acceder al mismo recurso debemos sincronizar los accesos al recurso para que no se produzcan inconsistencias en nuestras aplicaciones. Como el cerrojo intr´ ınseco pertenece al objeto. varios Hilos que o intentan acceder a un recurso compartido sincronizan su acceso a trav´s de un e cerrojo. recuerda que los Hilos y su sincronizaci´n son nativos en Java.5. 1 2 3 4 5 class A { synchronized void metodo1 ( ) {} synchronized void metodo2 ( ) {} . si e queremos sincronizar el acceso a un m´todo de un objeto basta marcarlo con la e palabra reservada synchronized.0 de Java.8. ¿Y donde se encuentran esos cerrojos que nos sirven para sincronizar el acceso a recursos compartidos?. Sincronizac´n utilizando los cerrojos intr´ o ınsecos En Java todo objeto posee un cerrojo intr´ ınseco que podemos utilizar para sincronizar el acceso a los recursos que nos proporciona el objeto. la sincronizaci´n en el ejemplo o del Listado 14. un m´todo es un recurso o servicio que proporciona un objeto.5. La sincronizaci´n en Java se base en el uso de cerrojos.

.. y esta es la diferencia o con respecto al m´todo sleep(int milisegundos) que provoca una espera del e 3 Existen otras dos versiones de este m´todo public final void wait(long timeout) e throws InterruptedException y public final void wait(long timeout. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class A { O b j e c t c e r r o j o 1 = new O b j e c t ( ) . no sincronizamos todo un m´todo si no s´lo las o e o l´ ıneas de c´digo que acceden al recurso compartido. O b j e c t c e r r o j o 2 = new O b j e c t ( ) .. Cuando un Hilo entra en espera. synchronized ( c e r r o j o 1 ) { // El a c c e s o a e s t e b l o q u e e s t ´ s i n c r o n i z a d o a // p o r c e r r o j o 1 . Incluso a veces nos interesa tener o o varios bloques de c´digo sincronizados pero que el acceso a distintos bloques de o c´digo no est´ sincronizado.9. Incluso podemos utilizar o esta t´cnica para sincronizar bloques de c´digo en distintos m´todos con el e o e mismo cerrojo. El acceso s´lo est´ sincronizado si el acceso es o a al mismo bloque de c´digo. por otra parte.9: Cada uno de los bloques de c´digo est´ sincronizado por un cerrojo o a intr´ ınseco de un objeto distinto. tal y como se muestra en el Listado 14.. libera el cerrojo intr´ ınseco que tenga en posesi´n. si no que la sincronizaci´n sea relativa al bloque y o e o no al objeto completo. si no sincronizar s´lo bloques de c´digo. y que el cerrojo se libera cuando el Hilo que lo o tiene en posesi´n acaba la ejecuci´n del m´todo o bloque sincronizado.. } } } Listado 14. pero ning´n otro Hilo podr´ acceder a estos bloques sincronizados u a hasta que los Hilos en posesi´n de los cerrojos no abandonen el bloque sincroo nizado. cualquier otro Hilo no podr´ acceder a ning´n otro m´todo definido a u e como synchronized.216 ´ CAP´ ITULO 14. Java nos permite sincronizar el acceso a bloque de c´digo tambi´n mediante o e el uso de la palabra reservada synchronized. } void metodo2 ( ) {} . Ya hemos visto que cuando un Hilo no puede adquirir el cerrojo para acceder a un m´todo o bloque sincronizado tiene que esperar a que el Hilo que tiene en e posesi´n el cerrojo lo libere. esta t´cnica nos permite sincronizar con m´s e a detalle el c´digo conflictivo. } . void metodo1 ( ) { .. Tambi´n o o e e podemos forzar que un Hilo entre en espera mediante el m´todo public final e void wait() throws InterruptedException3 . o F´ ıjate que. int nanos) throws InterruptedException . synchronized ( c e r r o j o 2 ) { // El a c c e s o a e s t e b l o q u e e s t ´ s i n c r o n i z a d o a // p o r c e r r o j o 2 . Un Hilo puede estar ejecutando el bloque sincronizado por el cerrojo1 mientras que otro Hilo puede estar ejecutando el bloque sincronizado por el cerrojo2. PROGRAMACION CONCURRENTE CON HILOS intr´ ınseco. Hay casos en los que no nos interesa sincronizar el acceso a los m´todo del e objeto.

de modo que. return d a t o . u e Alg´n otro Hilo llama al m´todo public final void notifyAll(). si el Hilo se despierta de modo o esp´reo puede que la condici´n siga sin satisfacerse. o c u p a c i o n −−. o c u p a c i o n ) . pero el Hilo no libera el cerrojo intr´ ınseco que tenga en posesi´n. } public synchronized void s e t D a t o (T d a t o ) throws I n t e r r u p t e d E x c e p t i o n { while ( o c u p a c i o n == c a p a c i d a d ) wait ( ) . datos [ ( cabeza + ocupacion ) % apacidad ] = dato . public B u f f e r S i n L o c k ( i n t c a p a c i d a d ) { super ( ) . System . . d a t o = (T) d a t o s [ c a b e z a ] .´ 14. SINCRONIZACION 217 Hilo. o Existe la posibilidad de que el Hilo en estado de espera sufra un despertar esp´reo. capacidad = capacidad .10 muestra una posible implementaci´n de un Buffer de tao ma˜o fijo con sus operaciones getDato() y setDato(T dato) sincronizadas y n de modo que si un Hilo intenta tomar un dato y el Buffer est´ vac´ el Hilo debe a ıo esperar (wait()). private i n t o c u p a c i o n = 0 . public c l a s s B u f f e r S i n L o c k <T> { private i n t c a b e z a = 0 . si detuvimos el Hilo porque no se comprobaba cierta condici´n. while ( o c u p a c i o n == 0 ) wait ( ) . El uso o del m´todo wait() lleva un Hilo desde el estado Ejecuci´n al estado Pausado e o ya que no conocemos cuando el Hilo volver´ al estado Ejecuci´n. por lo que siempre debeu o mos comprobar que la condici´n se satisface cuando un Hilo sale del estado de o espera. dato . private O b j e c t d a t o s [ ] . u e Mientras un Hilo permanece en estado de espera nunca ser´ elegido para a competir por la adquisici´n del cerrojo. d a t o s = new O b j e c t [ c a p a c i d a d ] . u e Alg´n otro Hilo llama al m´todo public void interrupt(). a o Un Hilo que ha entrado en espera mediante una llamada a wait() saldr´ de a este estado si ocurre alguna de estas cuatro cosas: Alg´n otro Hilo llama al m´todo public final void notify(). o u t . } @SuppressWarnings ( " u n c h e c k e d " ) public synchronized T g e t D a t o ( ) throws I n t e r r u p t e d E x c e p t i o n { T dato . c o c u p a c i o n ++. notifyAll () . cabeza % capacidad . dato . o u t . private i n t c a p a c i d a d . f o r m a t ( " + % s [ % d ] \ n " .% s [ % d ] \ n " . f o r m a t ( " . this . o c u p a c i o n ) . = System . c a b e z a ++.5. lo que implica que el Hilo se despierte aunque no ocurra ninguna u circunstancia de la indicada anteriormente. El Listado 14. notifyAll () . y si el Hilo intenta poner un nuevo dato y el Buffer est´ lleno a tambi´n debe esperar. e 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package b u f f e r .

10: Implementaci´n de un Buffer de tama˜o fijo utilizando cerrojos o n intr´ ınsecos En el Ap´ndice C se muestra un ejemplo de uso de este Buffer. debemos liberar el cerrojo.5. La idea b´sica es que un Hilo debe obtener el cerrojo que a representa alguna de estas clases antes de poder ejecutar el c´digo que nos ino teresa de manera concurrente. o o a Como ejemplo de funcionamiento de estas interfaces. . se ha enriquecido el API de Java con nuevos paquetes o para facilitar la programaci´n con Hilos.WriteLock son de gran ayuda. En el Ap´ndice C se muestra un ejemplo de uso de este Buffer. java. } Listado 14. e 1 2 package b u f f e r . . La t´cnica recomendada para hacerlo e se muestra en el Listado 14.concurrent. try { // a c c e s o a l o s r e c u r s o s c o m p a r t i d o s } finally { l . liberando el Lock. e 14.11: Modo aconsejado de trabajar con los objetos que implementan la interface Lock Otra interface de gran ayuda es Condition con la que podemos definir varias condiciones sobre un mismo Lock de modo que el hilo que adquiere el Lock puede pausarse. o El ultimo paquete java.concurrent. el Listado 14. Sincronizaci´n utilizando el interface Lock o Desde la versi´n Java 5. utilizando un Condition si la condici´n o de ocupaci´n del Hilo no es v´lida. y se le informar´ a trav´s de esa misma o a a e Condition de que la condici´n de ocupaci´n del Hilo puede ser v´lida de nuevo. o n como el del Listado 14.atomic Conjunto de clases para acceso at´mico a tio pos de datos primitivos y referencia. unlock ( ) . . ReentrantReadWriteLock.218 36 37 ´ CAP´ ITULO 14.locks de la lista anterior propor´ ciona clases que facilitan la sincronizaci´n concurrente a recursos compartidos.10 pero esta vez haciendo uso de estas interfaces. java.util.util.ReadLock y ReentrantReadWriteLock.12 muestra una implementaci´n de un Buffer de tama˜o fijo y acceso sincronizado. o En particular la interface Lock y las clases que lo implementan ReentrantLock. // creamos a l g u n a i n s t a n c i a que implemente a Lock l . PROGRAMACION CONCURRENTE CON HILOS } } Listado 14.concurrent Que proporciona nuevas estructuras de datos y clases de utilidad de acceso concurrente.11 1 2 3 4 5 6 7 Lock l = .util.concurrent. . y una vez que se ha terminado la ejecuci´n del o c´digo cr´ o ıtico.locks Conjunto de clases para facilitar la sincronizaci´n y acceso concurrente a recursos compartidos.2.util. lock () . Estos nuevos paquetes son: o java.

o c u p a c i o n ) . f o r m a t ( " + % s [ % d ] \ n " . l o c k s . l o c k s . private i n t o c u p a c i o n = 0 . this . o c u p a c i o n −−. } } } Listado 14. Lock . . d a t o = (T) d a t o s [ c a b e z a ] . } public void s e t D a t o (T d a t o ) throws I n t e r r u p t e d E x c e p t i o n { cerrojo . u t i l . import j a v a . c o n d i c i o n = c e r r o j o . o u t . private O b j e c t d a t o s [ ] . SINCRONIZACION 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 219 import j a v a . capacidad = capacidad . await ( ) . u t i l . La secci´n 13. cabeza % capacidad . c e r r o j o .5.12: Implementaci´n de un Buffer de tama˜o fijo utilizando las clases o n ReentrantLock y Condition ¿Cuando utilizar los cerrojos intr´ ınsecos y cuando el interface Lock?. dato . public c l a s s BufferConLock<T> { private i n t c a b e z a = 0 . try { while ( o c u p a c i o n == c a p a c i d a d ) condicion . try { while ( o c u p a c i o n == 0 ) condicion . d a t o s = new O b j e c t [ c a p a c i d a d ] . o c u p a c i o n ) . unlock ( ) . } return d a t o .2 de la referencia [1] clarifica mucho cuando utilizar una t´cnica u o e otra. private Lock c e r r o j o . c o n c u r r e n t . newCondition ( ) . Escribe una aplicaci´n en la que varios Hilos intenten acceder a un recurso o compartido que muestre un mensaje por consola. c e r r o j o = new R e e n t r a n t L o c k ( ) . El acceso a este recurso compartido debe hacerse de modo sincronizado. import j a v a . lock () . = System . f o r m a t ( " . dato . cerrojo . c o c u p a c i o n ++. c e r r o j o . C o n d i t i o n . c o n c u r r e n t . signalAll () . c a b e z a ++. unlock ( ) . 1. private i n t c a p a c i d a d . private C o n d i t i o n c o n d i c i o n . System . } finally { condicion . u t i l . public Bu ffe rC onL ock ( i n t c a p a c i d a d ) { super ( ) . o u t . } finally { condicion . signalAll () . datos [ ( cabeza + ocupacion ) % apacidad ] = dato . } @SuppressWarnings ( " u n c h e c k e d " ) public T g e t D a t o ( ) throws I n t e r r u p t e d E x c e p t i o n { T dato . R e e n t r a n t L o c k .% s [ % d ] \ n " .´ 14. Ejercicios. await ( ) . lock () . l o c k s . c o n c u r r e n t .

El Cap´ ıtulo 10 de la referencia [2] es sin duda una muy buena exposici´n o de las t´cnicas de concurrencia en Java utilizando cerrojos intr´ e ınsecos. PROGRAMACION CONCURRENTE CON HILOS Lecturas recomendadas. El Cap´ ıtulo 9 de la referencia [4] expone criterios muy interesante a seguir en el uso de Hilos para que no se vea reducida la potencia de nuestras aplicaciones por un mal uso de los Hilos. La referencia [1] es obligada de principio a fin si la concurrencia es capital en nuestras aplicaciones.220 ´ CAP´ ITULO 14. .

. .1. . . .2. . . Java nos permite trabajar en red de un modo muy sencillo gracias a la gran cantidad de clases que nos proporciona el paquete java. 15. . . . . . . . . Trabajo con URLs . . ¿Qu´ es una URL? . .3. . . . . . e 15.2. . y como trabajar con Sockets tanto bajo el protocolo TCP como bajo el protocolo UDP. . . . . . Sockets UDP en el lado del servidor 15. Como ver´s.1. . . . En el Cap´ ıtulo 12 vimos c´mo programar Applets. . . .1.2. . . . . . .1. . . . En este cap´ ıtulo veremos como trabajar con URLs. . . . . Sockets bajo el protocolo TCP . . Recuerda que todo proceso de lectura/escritura es independiente del dispositivo de entrada/salida y se realiza a trav´s de Flujos. Sockets TCP en el lado del cliente . . . . pilar b´sico para refea renciar recursos en el protocolo HTTP. 15. . . . . . . . . . de e ah´ la importancia de conocerlos a fondo. . . . Sockets TCP en el lado del servidor 15. . . . . . Escribir a una URL . . . . . . . . . . . . ¿Qu´ es un Socket? . . Sockets UDP en el lado del cliente . 15.2. . . . . . . .2.net. . . .2.1. . . . . .3. 15.2. . . . . 222 222 223 223 225 225 225 225 226 227 228 228 Introducci´n o Java naci´ como un lenguaje de prop´sito general con grandes capacidades para o o trabajar en red. .2. .Cap´ ıtulo 15 Programaci´n para la Red o Contenidos 15. . ı 221 . . . . 15. . . . . . tanto si trabajamos con URLs como si trabajamos con Sockets. . . .3.2. . .2. . . . . . . .2. . .2. . . a la lectura y escritura sobre estos canales la haremos a trav´s de los Flujos que e vimos en el Cap´ ıtulo 7. 15. . . .1.2. . Sockets bajo el protocolo UDP . que son o aplicaciones Java que se ejecutan en el contexto de un navegador web.3. . . 15. . . . Trabajo con Sockets . Leer desde una URL . . . . .1. . .2. . .1. e 15.

1. URL u r l = new URL( " h t t p " . 15. " i n d e x . Veremos que en el paquete o e java. Este recurso viene especificado por cuatro partes. ¿Qu´ es una URL? e Una URL representa un recurso en Internet. devuelve el puerto de conexi´n.cgi a e . public String getHost(). e s : 8 0 / i n d e x . Listado 15. Esta clase nos permite tanto leer el contenido de la URL como escribir hacia la URL. o aunque.es. u j i . o index.html1 . e s " . " i n d e x . PROGRAMACION PARA LA RED 15. por ejemplo en la siguiente URL http://www. g o o g l e .google. como en el tercer caso.net tenemos una clase para crear URLs.google. h t m l " ) . e s " . 3. o Si el protocolo tiene un puerto bien conocido no hace falta especificarlo. En el segundo caso lo especificamos como cuatro cadenas ´ indicando el protocolo. El puerto de conexi´n 80. y si no se indica la contrario. o public String getFile(). " w w w . a 1 2 3 URL u r l = new URL( " h t t p : / / w w w .js. por lo que la anterior URL la podemos escribir de forma abreviada de modo http://www. h t m l " ) . 8 0 . devuelve el recurso que se solicita. Los servidores que atienden peticiones HTTP generalmente utilizan el puerto de escucha 80. URL u r l = new URL( " h t t p " . Todos estos constructores pueden lanzar una excepci´n de tipo o MalformedURLException para indicar que la URL que se intenta especificar no es v´lida.google. devuelve el host. " w w w . En esta secci´n vamos a utilizar como ejemplo siempre el protocolo HTTP.222 ´ CAP´ ITULO 15.1: Algunos constructores de la clase URL La clase URL nos proporciona m´todos para recuperar la informaci´n contee o nida en una URL: public String getProtocol().html. Pasemos ahora a ver c´mo leer desde una URL.1. u j i . public int getPort().html. puerto y recurso respectivamente. En el primer caso especificamos la URL como una unica cadena. 2. o 4. el fichero al que por defecto se accede es index. como el lector sabr´.1. Trabajo con URLs En esta secci´n vamos a recordar qu´ es una URL. h t m l " ) . o 1 La p´gina de inicio de un sitio web tambi´n puede ser index. a Java nos proporciona la clase URL para poder especificar recursos en Internet como muestra el Listado 15.1.es. existe otra gran cantidad de protocolos sobre TCP. El protocolo http. se est´ especificando: a 1.es: 80/index. El host de destino www. direcci´n de Internet. devuelve el protocolo. El fichero solicitado index.

. i o . try { S t r i n g cadena . para lo que utilizaremos el m´todo public void e setDoOutput(boolean dooutput) de la clase URLConnection con un argumento true. e j e c u t a ( a r g s [ 0 ] ) . o u t . . y como ya vimos en el Cap´ ıtulo 7 a partir de una referencia de tipo InputStream podemos recuperar un BufferedReader con el que leer l´ ınea a l´ ınea desde el recurso. B u f f e r e d R e a d e r br = new B u f f e r e d R e a d e r (new I n p u t S t r e a m R e a d e r ( i s ) ) . Escribir a una URL Escribir a una URL exige un poco m´s de trabajo. printStackTrace () .3. } private void e j e c u t a ( S t r i n g d i r e c c i o n ) { try { URL u r l = new URL( d i r e c c i o n ) . podemos recuperar a partir a de ella un InputStream para leer el contenido del recurso al que apunta la URL. } finally { br . BufferedReader .1.1.URL. InputStreamReader . i o . public f i n a l c l a s s LeerDesdeURL { private LeerDesdeURL ( ) { super ( ) .2: Lectura desde una URL 15. printStackTrace () . mediante el m´todo public final InputStream openStream() throws e IOException. n e t . . I n p u t S t r e a m i s = u r l . c l o s e ( ) . TRABAJO CON URLS 223 15.2. } } public s t a t i c void main ( S t r i n g [ ] a r g s ) { new LeerDesdeURL ( ) . MalformedURLException . while ( ( cadena = br . InputStream . debemos indicar que queremos escribir sobre ella. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package r e d . . ya que no podemos a escribir directamente a una URL.1. r e a d L i n e ( ) ) != n u l l ) System . Una vez obtenida esta referencia. p r i n t l n ( cadena ) . .2 muestra un ejemplo completo de c´mo o leer el contenido de un fichero de esto apuntado por una URL. n e t . } } Listado 15. } } catch ( MalformedURLException e ) { e . openStream ( ) . } catch ( I O E x c e p t i o n e ) { e . IOException . i o .15. import import import import import import java java java java java java . io . La referencia necesaria nos la devuelve el m´todo public URLConnection openConnection() throws IOException e de la clase URL. El Listado 15. Ahora ya podemos recuperar un OutputStream con el m´todo e public OutputStream getOutputStream() throws IOException de la clase URConnection . Para escribir a una URL necesitamos una referencia a la clase URLConnection. Leer desde una URL Una vez que tenemos construida una URL v´lida.

c l o s e ( ) . .dlsi. n e t . getOutputStream ( ) . try { String respuesta .3 muestra todos los pasos necesarios para escribir a una URL y obtener una respuesta de ella. .es/ oscao r/PHP/nombre.URL. i o . n e t . import import import import import import import java java java java java java java . } private void e j e c u t a ( S t r i n g s U r l ) { try { URL u r l = new URL( s U r l ) . io .3: Escritura a una URL En el Listado 15. io . PROGRAMACION PARA LA RED El Listado 15. MalformedURLException . o u t . true ) . o p e n C o n n e c t i o n ( ) . BufferedReader .php?nombre=oscar y obtendr´s un saludo como respuesta a ..uji. o 2 Para ver el resultado en un navegador. p r i n t l n ( r e s p u e s t a ) . HEAD. i o . n e t . En este caso hemos utilizado la direcci´n o http://rubi. InputStreamReader . . IOException . printStackTrace () . B u f f e r e d R e a d e r br = new B u f f e r e d R e a d e r (new I n p u t S t r e a m R e a d e r ( c o n e x i o n .uji.dlsi. r e a d L i n e ( ) ) != n u l l ) System . etc. Si el protocolo que utilizamos en la conexi´n es HTTP. } catch ( I O E x c e p t i o n e ) { e .3. br . } } Listado 15. PrintWriter . URLConnection . . setDoOutput ( true ) . podemos moo delar la referencia de respuesta del m´todo openConnection() al tipo e HttpURLConnection. y otros m´todos interesantes para saber el c´digo de ese o tado de la petici´n (public int getResponseCode() throws IOException). URLConnection c o n e x i o n = u r l . } finally { pw . getInputStream ( ) ) ) .224 ´ CAP´ ITULO 15. } } catch ( MalformedURLException e ) { e . c o n e x i o n . while ( ( r e s p u e s t a = br . . printStackTrace () . c l o s e ( ) . presta atenci´n al segundo par´metro del constructor o a de PrintWriter que es true para indicar que se haga auto-flush cada vez que escribimos en el stream.es/~oscar/PHP/nombre. pw . Esta nueva clase tiene m´todos que nos permiten especifie car el tipo de petici´n que se realiza public void setRequestMethod(String o method) throws ProtocolException para indicar si la petici´n es GET. teclea la direcci´n http://rubi. P r i n t W r i t e r pw = new P r i n t W r i t e r ( c o n e x i o n . public f i n a l c l a s s EscribirAURL { private EscribirAURL ( ) { super ( ) . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package r e d . .php que espera un par´mea tro de entrada llamado nombre y devuelve un saludo2 . p r i n t l n ( " n o m b r e = o s c a r " ) . e j e c u t a ( a r g s [ 0 ] ) . o POST. } } public s t a t i c void main ( S t r i n g [ ] a r g s ) { new EscribirAURL ( ) .

¿Qu´ es un Socket? e Un Socket es cada uno de los extremos que se establece en una comunicaci´n.net. Trabajo con Sockets Los Sockets son el ladrillo fundamental en comunicaciones a trav´s del protocolo e TCP o UDP.2. es decir. ServerSocket . en la que se reserva un canal por el que la informaci´n circula sin e o p´rdidas y de manera ordenada. import import import import java java java java . a partir de la cual podremos obtener Flujos de lectura o escritura. .2. TRABAJO CON SOCKETS 225 15. o en toda comunicaci´n tendremos un Socket en el lado del emisor y un Socket o en el lado del receptor. io .1. el protocolo TCP est´ orientado a la conexi´n. En el paquete java. El Listado 15. 15. Entre otras cosas el protocolo TCP garantiza la recepci´n o de los datos en el mismo orden en que se emiten y sin p´rdidas.1. Socket . el m´todo e accept() nos devolver´ una referencia al Socket cliente (instancia de la clase a Socket esta vez). Sockets bajo el protocolo TCP En las conexiones bajo el protocolo TCP existe un canal de conexi´n entre el o cliente y el servidor. . la ejecuci´n se detiene en este m´todo hasta que un cliente o e se conecta. que es e bloqueante.15.ServerSocket.2. Para aceptar conexiones utilizamos el m´todo public Socket accept() throws IOException. a 15. } .2. 1 2 3 4 5 6 7 8 9 10 11 12 package r e d . Sockets TCP en el lado del servidor Para crear un Socket que acepte conexiones en un determinado puerto. En la l´ ınea 41 puedes ver c´mo la clase o Socket nos devuelve un Flujo de escritura para comunicarnos con el cliente.2.2.4 muestra un ejemplo de un sencillo Servidor que env´ un ıa saludo a cada cliente que se le conecta. mientras que el protocolo UDP a o est´ orientado al mensaje. net . IOException . El s´ e ımil que se utiliza para visualizar las conexiones bajo el protocolo TCP es el de una llamada de tel´fono.net encontramos clases para trabajar con Sockets tanto bajo el protocolo TCP como bajo el protocolo UDP.2. i o . PrintWriter . Como en el caso del trabajos con URLs veremos que una vez establecida la conexi´n entre dos Sockets (cliente/servidor) todas las tareas de o lectura y escritura entre los Sockets se realizar´n sobre los Flujos que la clase a Socket nos proporciona. en el momento de crear una instancia de esta clase indicamos el puerto de escucha. Como recordatorio. net . . Cada vez que un cliente se conecta al Socket servidor. public f i n a l c l a s s S e r v i d o r S e n c i l l o { private S e r v i d o r S e n c i l l o ( ) { super ( ) . e 15. Java nos proporciona la clase java.

o u t . y una vez establecida la conexi´n o podremos abrir Flujos de lectura y escritura. printStackTrace () .Socket. El Listado 15. Tambi´n puedes conectarte al servidor mediante telnet escribiendo e en una consola telnet localhost 1234. p r i n t l n ( " S e r v i d o r a l a e s c u c h a " ) . pw . } } catch ( I O E x c e p t i o n e ) { e .5 muestra un ejemplo de un cliente que se conecta al servidor del Listado 15.2. a c c e p t ( ) ) != n u l l ) new Thread (new S a l u d o ( c l i e n t e ) ) . 15. o u t . printStackTrace () . true ) . public S a l u d o ( S o c k e t c l i e n t e ) { this .net. pw . // Creamos un S o c k e t s e r v i d o r a l a e s c u c h a en e l p u e r t o i n d i c a d o S e r v e r S o c k e t s e r v i d o r = new S e r v e r S o c k e t ( p u e r t o ) . Al crear una instancia de esta clase le pasamos la direcci´n o a la que nos queremos conectar y en que puerto. por ejemplo. .4: Un Socket servidor que env´ un saludo a cada cliente que se le ıa conecta Si. s t a r t ( ) . } catch ( I O E x c e p t i o n e ) { e . try { // Obtenemos un s t r e a m de e s c r i t u r a a p a r t i r d e l S o c k e t d e l c l i e n t e P r i n t W r i t e r pw = new P r i n t W r i t e r ( c l i e n t e . p r i n t l n ( " H o l a d e s d e e l s e r v i d o r " ) . e j e c u t a ( I n t e g e r . getOutputStream ( ) . pasando este entero por la l´ ınea de argumentos. } } } public s t a t i c void main ( S t r i n g a r g s [ ] ) { new S e r v i d o r S e n c i l l o ( ) . inicias el servidor en el puerto 1234. close () . Y obtendr´s como resultado el mensaje o a de saludo.2.4 para obtener un saludo como respuesta. Socket c l i e n t e . } } private c l a s s S a l u d o implements Runnable { private S o c k e t c l i e n t e .226 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 ´ CAP´ ITULO 15. } } Listado 15. Sockets TCP en el lado del cliente Para conectarnos a un Socket servidor desde Java disponemos de la clase java. podr´s conectarte al servidor desde un navegador web en a la direcci´n http://localhost:1234. p a r s e I n t ( a r g s [ 0 ] ) ) . PROGRAMACION PARA LA RED private void e j e c u t a ( i n t p u e r t o ) { try { System . c l i e n t e = c l i e n t e . try { // Cada v e z que s e c o n e c t a un c l i e n t e l e enviamos un s a l u d o while ( ( c l i e n t e = s e r v i d o r . c l o s e ( ) . } @Override public void run ( ) { System . } finally { servidor . p r i n t l n ( " C l i e n t e c o n e c t a d o " ) .2. 1 2 package r e d .

2. o un Socket UDP capaz de enviar datos a un determinado servidor. printStackTrace () . La clase DatagramSocket es la que se encarga de enviar o recibir cada uno de los DatagramPacket. } } public s t a t i c void main ( S t r i n g [ ] a r g s ) { new C l i e n t e S e n c i l l o ( ) . getInputStream ( ) ) ) .15. public f i n a l c l a s s C l i e n t e S e n c i l l o { private C l i e n t e S e n c i l l o ( ) { super ( ) . De modo an´logo. o u t .5: Un Socket clinet que conecta al anterior servidor para recibir un saludo. } finally { i f ( c l i e n t e != n u l l ) c l i e n t e . y tampoco se garantiza que al receptor lleguen todos los mensajes del emisor. BufferedReader . p u e r t o ) .2. existe la posibilidad de que alguno se pierda por el camino. } } catch ( UnknownHostException e ) { e . Sockets bajo el protocolo UDP En el caso del Protocolo UDP no se garantiza que los mensajes recibidos lo hagan en el mismo orden que los enviados. i o . o un datagrama para recibir datos. . . String saludo . UnknownHostException . io . e En el caso del protocolo UDP. . TRABAJO CON SOCKETS 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 227 import import import import import java java java java java . while ( ( s a l u d o = br . } } Listado 15. n e t . 15. try { // Recupero un s t r e a m de l e c t u r a B u f f e r e d R e a d e r br = new B u f f e r e d R e a d e r (new I n p u t S t r e a m R e a d e r ( c l i e n t e . printStackTrace () . En el caso del protocolo UDP disponemos de dos clases para realizar la comunicaci´n. e j e c u t a ( I n t e g e r . dependiendo del constructor que utilicemos para instana ciar la clase DatagramSocket estaremos creando un Socket UDP capaz de recibir datos en un cierto puerto.3. InputStreamReader . La clase DatagramPacket la utilizaremos para especificar los datos o que queremos enviar o recibir. r e a d L i n e ( ) ) != n u l l ) System . . i o . al contrario que en el caso del protocolo TCP. } private void e j e c u t a ( i n t p u e r t o ) { try { // Me c o n e c t o a l s e r v i d o r l o c a l que e s c u h a e s e s t e p u e r t o S o c k e t c l i e n t e = new S o c k e t ( " l o c a l h o s t " . no disponemos de dos clases diferenciadas dependiendo de si lo que queremos crear es un Socket servidor o un Socket cliente. Dependiendo del constructor que utilicemos para instanciar la clase DatagramPacket estaremos creando un datagrama para enviar datos. } catch ( I O E x c e p t i o n e ) { e . . p r i n t l n ( s a l u d o ) . net . p a r s e I n t ( a r g s [ 0 ] ) ) . c l o s e ( ) . Socket . IOException . En este caso el s´ ımil que se utiliza es el de comunicaciones a trav´s de un servicio postal.

la clase DatagramSocket nos permitir´ tanto enviar como recibir paquetes en el puerto a indicado. Listado 15. p r i n t l n ( " H o s t c l i e n t e : " + d i r e c c i o n C l i e n t e . l e n g t h ) . El listado 15.8 se muestra un ejemplo de env´ de un ıo paquete hacia un servidor UDP.6: Lectura de un paquete mediante el protocolo UDP. DatagramSocket s e r v i d o r = new DatagramSocket ( 1 2 3 4 5 ) .3. ıa 7 8 9 bytes [ ] mensaje = " Hola " . por ejemplo new DatagramPacket(new byte[1].228 15.2.2.6 donde el servidor env´ un paquete de respuesta al cliente. 100) nos permitir´ leer a hasta 100 bytes del paquete recibido. Finalmente. ´ CAP´ ITULO 15.7 es una continuaci´n o del listado 15. 1. o u t . pero esta vez. a n por ejemplo new DatagramPacket(new byte[100]. // P u e r t o de e s c u c h a 12345 s e r v i d o r . inetAddress. getSocketAddress ( ) .7: Escritura de un paquete mediante el protocolo UDP. SocketAddress direccion). El Listado 15. d i r e c c i o n C l i e n t e ) . al crear una instancia de DatagramPacket.1. m e n s a j e . PROGRAMACION PARA LA RED Sockets UDP en el lado del servidor Para crear un Socket UDP en el lado del servidor debemos utilizar el constructor de la clase DatagramSocket que recibe como par´metro el puerto de conexi´n a o public DatagramSocket(int puerto). 15. s e r v i d o r . Para recibir paquetes necesitamos crear una instancia de la clase DatagramPacket indicando el buffer sobre el que se leer´n los datos y su tama˜o.2. 12345). length . b u f f e r . para enviar el paquete utilizaremos de nuevo el m´todo send(paquete) de la clae se DatagramSocket. send ( paqueteRespuesta ) . Para enviar un paquete como contestaci´n al cliente del que se acaba de o recibir un paquete crear´ ıamos una nueva instancia de la clase DatagramPacket pero esta vez utilizando el constructor que incluye un tercer par´metro con la dia recci´n de destino del paquete public DatagramPacket(byte[] buffer. si el paquete recibido contiene m´s de a 100 bytes. DatagramPacket p a q u e t e R e s p u e s t a = new DatagramPacket ( mensaje .3.7. int o tamBuffer. es posible utilizar la misma instancia de la clase DatagramSocket para enviar datos. DatagramPacket p a q u e t e = new DatagramPacket ( b u f f e r . 1 2 3 4 5 6 byte [ ] b u f f e r = new byte [ 8 ∗ 1 0 2 4 ] . getBytes ( ) . el resto ser´ ignorado. // El m´ todo r e c e i v e e s b l o q u e a n t e e InetSocketAddress d i r e c c i o n C l i e n t e = paquete . En el Listado 15. Una vez creado el Socket UDP. indicamos la direcci´n y el puerto del servidor al que quereo mos hacer llegar el paquete. r e c e i v e ( p a q u e t e ) . . La direcci´n a la cual se o debe enviar el paquete la obtiene la clase DatagramSocket a partir de la clase DatagramPacket. Sockets UDP en el lado del cliente Para escribir un cliente utilizando el protocolo UDP utilizamos de nuevo las clases DatagramPacket y DatagramSocket. Como puedes observar en el Listado 15. Listado 15. Para crear la instancia de DatagramSocket utilizaremos el constructor por defecto new DatagramSocket(). getHostName ( ) ) .6 muestra un ejemplo de lectura a de un paquete UDP. System .

e 2. 1 . Al utilizar Sockets bajo el protocolo TCP. Tanto el m´todo accept() de la clase ServerSocket como el m´todo e e receive() de la clase DatagramSocket son bloqueantes. 1. Itenta crear una aplicaci´n de chat. 1. 12345) . p a q u e t e = new DatagramPacket ( b u f f e r . buffer .2. Listado 15. como se muestra en el Listado 15. el cliente puede quedar a la escucha de los paquetes que reciba desde el servidor. o 4 5 6 byte [ ] b u f f e r = new byte [ 8 ∗ 1 0 2 4 ] . send ( paquete ) . En la aplicaci´n hay una parte de o o servidor.8. El protocolo UDP tampoco tiene en cuenta que el orden de los paquetes recibidos es el mismo que el de los paquetes enviados. inetAddress . ¿C´mo puedes darte cuenta de o que la conexi´n entre el cliente y el servidor se ha cortado? ¿Y en el caso o del protocolo UDP? Ejercicios. DatagramSocket s e r v i d o r = new DatagramSocket ( ) . que atiende la conexi´n de nuevos clientes. o Cuestiones. Listado 15. ıan Lecturas recomendadas. ¿Qu´ debes utie lizar para que tu aplicaci´n no se quede ((congelada)) esperando a que se o retorne de estos dos m´todos?.15. s e r v i d o r . s e r v i d o r . Cada vez que un o cliente se conecta al servidor de chat queda registrado de modo que recibe todos los mensajes que env´ el resto de clientes. TRABAJO CON SOCKETS 229 1 2 3 DatagramPacket p a q u e t e = new DatagramPacket (new byte [ 1 ] .9 que es continuaci´n del Listado 15. ¿C´mo podr´ asegurarte de que s´ que llega a su destino? o ıas ı 3.9: Recepci´n de paquetes por parte de un cliente. length ) . o . Una excelente referencia para casi cualquier tema relacionado con la programaci´n para la red es el libro de Elliotte Rusty Harold [12].8: Env´ de un paquete mediante el protocolo UDP desde un cliente ıo a un servidor. ¿C´mo podr´ o ıas reordenar los paquetes que recibe tu aplicaci´n para garantizar que siguen o el mismo orden con el que se enviaron? 4. El protocolo UDP no comprueba que un paquete ha llegado efectivamente a su destino. Igual que en el caso del servidor. r e c e i v e ( paquete ) .

PROGRAMACION PARA LA RED .230 ´ CAP´ ITULO 15.

. Situaci´n que intenta resolver . en primer lugar y a modo de resumen. . l patr´n de dise˜ o Decorator . o A continuaci´n se define lo que son los patrones de dise˜o software y por o n 231 . . . . . . . . . .7. . . . . . o 16. El patr´n de dise˜ o Strategy . . . . . . . . . . .1. los Principios de Programaci´n Orientada a Objetos. . . Situaci´n que intenta resolver . . . . . . o n 16. . . . . .6. .7. . . . . . .1. . . Situaci´n que intenta resolver .6. . .9. . . . . . . . . .8. . . Ejemplo de implementaci´n . . o 16.1. Introducci´n o En este cap´ ıtulo se presenta. o n 16.Cap´ ıtulo 16 Patrones de dise˜ o n Contenidos 16. . . . .2. . . . . . o 16. . El patr´n de dise˜ o Abstract Factory . . . . ¿Qu´ son los patrones de dise˜ o? . .1. . . . . . . . . . . 16. . . 16. o n 16. . . . . . . o n 16. .1. . . Situaci´n que intenta resolver .7. . . o 16. . .10. e n 16.10. . . . . . . . . . . . . El patr´n de dise˜ o Observer . . . . . . o 16. . . . . . . . . . o 16. . . . . n 16.2. . . . E o n 16. . . . . . . . . . . o 16.1. . . Ejemplo de implementaci´n . ¿Qu´ es el acoplamiento entre clases y por qu´ hay e e que evitarlo? . . .4. . . . o 16. . . . . . . .2. . . . . o 16. . . .8. .9. o n 16. . . . . . . . .2. . . . . . . . . . . . . . .5. . Situaci´n que intenta resolver .2. . . . . . o 16. . . . . . . .6. . . . . . . . . .5. . .2. . Grupos de patrones de dise˜ o .1. .2. . . . . .3. . .8. . . Principios de POO . . Ejemplo de implementaci´n . .5. . . . . . . . . . . . Ejemplo de implementaci´n . . . . . . . . o 232 233 233 233 233 234 234 235 235 236 238 238 238 244 245 245 247 247 248 249 250 250 . . El patr´n de dise˜ o Singleton . . . . . .Situaci´n que intenta resolver . . Ejemplo de implementaci´n . . . El patr´n de dise˜ o Factory Method .Ejemplo de implementaci´n . .9. . . . . . . . . . . . .10. . . . o 16.

o Evitar el acoplamiento entre clases. PATRONES DE DISENO qu´ son utiles. o Interface segregation Una clase s´lo debe implementar un interface si es neo cesario que ofrezca todos los m´todos que declara el interface. es soluciones bien conocidas a problemas recurrentes en el dise˜o del software. Dependency inversion Las clases no deben crear instancias de otras clases con las que trabajen. Open close principle La definici´n de una clase debe ser abierta para su exo tensi´n pero cerrada para su modificaci´n. Principios de POO A lo largo de este libro se ha intentado presentar no s´lo el lenguaje de prograo maci´n Java. o o Liskov substitution Siempre debe ser posible sustituir una clase padre por otra hija sin que cambie el comportamiento de la aplicaci´n. n . o Programar orientado a la interface no a la implementaci´n. Estos principios establecen: n Single responsability Una clase debe tener una unica responsabilidad que ´ justifique su existencia. Y precisamente n estas soluciones son lo que se conoce como Patrones de dise˜o. Las buenas pr´cticas aplicadas al dise˜o de software orientado a a n objetos constituyen sus principios. y las herramientas de ayuda en el desarrollo de proyectos. Favorecer la composici´n frente a la herencia. la dependencia de una clase con respecto de otra debe inyectarse desde fuera de la clase. o 16. Los principios SOLID son otro grupo de principios a tener en cuenta en el dise˜o de software. unas normas de car´cter general que conviene a seguir en la construcci´n de software. Reducir la responsabilidad de cada clase. e ´ El grueso del cap´ ıtulo lo forma la presentaci´n de algunos de los patrones de o dise˜o m´s utilizados en el desarrollo de proyectos inform´ticos. si no o tambi´n las buenas pr´cticas a seguir en la codificaci´n y en el dise˜o de nuestras e a o n aplicaciones. a veces. Estos principios generales pueden concretarse.1. Siguiendo las expuestas en las referencias o [8] y [9] y de modo resumido y son: Encapsular lo que var´ ıa. son n a u o directrices que nos pueden ayudar en la escritura de c´digo. Los patrones n a a de dise˜o no est´n ligados a ning´n lenguaje de programaci´n en particular.232 ˜ CAP´ ITULO 16. y no s´lo e o unos cuantos.

las clases cliente fuertemente acopladas con ella o dejan de funcionar. Observer ) y estructurales (Decorator ) entre los m´s a conocidos sin ser una lista exhaustiva. ¿Qu´ es el acoplamiento entre clases y por e qu´ hay que evitarlo? e Cuando al utilizar una clase desde el c´digo de otra.5. Por cuesti´n de espacio presentamos los o indicados entre par´ntesis. o suele tener. El acoplamiento muchas veces implica que al cambiar la implementaci´n de una clase. lo que define un vocabulario com´n que facilita el intercambio u de ideas.2. Abstract factory). o o Lo que hay que evitar. la independencia de la a n implementaci´n concreta entre clases.4. El patr´n de dise˜ o Singleton o n Aparentemente este es un patr´n de dise˜o muy sencillo que acaba teniendo o n una implementaci´n sofisticada cuando se utiliza en ambientes de programaci´n o o concurrente. ante todo. ¿QUE SON LOS PATRONES DE DISENO? 233 16.2. en el cap´ ´ o n ıtulo 11. 16. ¿Qu´ son los patrones de dise˜ o? e n Es usual que. as´ nos encontramos con n ı patrones de dise˜o de creaci´n (Singleton.3. Esta coyuntura finalmente desemboca en una serie de modificaciones en cascada a lo largo y ancho del c´digo de la aplicaci´n. Y este es el principio o b´sico que encontramos en todos los patrones de dise˜o. de n o comportamiento (Strategy. durante el desarrollo de un proyecto inform´tico. y una plantilla de aplicaci´n que muestra cuales son sus componentes o y c´mo se relacionan entre si. nos encontremos a de modo recurrente con el mismo tipo de problemas. Grupos de patrones de dise˜ o n Los patrones de dise˜o se agrupan por su cometido.´ ˜ 16. MVC. . Los patrones de dise˜o son soluciones bien conocidas y ampliamente emn pleadas para resolver problemas recurrentes en el dise˜o de aplicaciones inn form´ticas. Factory method. Por ejemplo c´mo garano tizar la existencia de una unica instancia para poder acceder a un determinado ´ dispositivo. dejando el resto para su consulta en la bibliograf´ e ıa. Cada uno de los patrones de dise˜o tiene. o 16. o 16. En este u ultimo caso ya has visto un patr´n de dise˜o muy potente. deben ser modificadas para reflejar los cambios en la clase inicial. O c´mo estructurar una aplicaci´n basada en un iterface gr´fico o o a para que me permita m´ltiples representaciones de los mismos datos. un nombre a n estandarizado. la clase cliente conoce detao lles de la implementaci´n de la clase que utiliza decimos que las dos clases est´n o a fuertemente acopladas. es que una clase dependa de los detalles de implementaci´n de otra para que pueda utilizarla.

1. } } Listado 16. el modificador final no es necesario. private S i n g l e t o n ( ) { super ( ) .1: Implementaci´n sencilla del patr´n Singleton o o Como ves. Por otro lado. se cede la ejecuci´n al o segundo hilo. El o o n las l´ ıneas 4-6 definimos como private el constructor por defecto de la clase. Este patr´n de dise˜o es util cuando queremos garantiza la unicidad de una o n ´ instancia. Esta implementaci´n es completamente funcional si o nuestra aplicaci´n no utiliza hilos.1 se muestra una implementaci´n de este patr´n de dise˜o. que ser´ la que a devolvamos cada vez que se pida a trav´s de la llamada al m´todo getInstancia() e e definido entra las l´ ıneas 8-12. Veamos cual es el o problema que puede aparecer. 16. recordemos que la intenci´n de o este patr´n de dise˜o es que unicamente exista una instancia de la clase Singleo n ´ ton.5. pero en caso de utilizarlos podemos encono trarnos con problemas al usar esta sencilla implementaci´n. Suponga´ u mos que uno de los hilos llama al m´todo getInstancia(). 1 2 3 4 5 6 7 8 9 10 11 12 13 public c l a s s S i n g l e t o n { private S i n g l e t o n i n s t a n c i a = n u l l . PATRONES DE DISENO 16. y que por simplicidad s´lo o contamos con un procesador (o un procesador con un unico n´cleo). return i n s t a n c i a . al existir unicamente el constructor por defecto con acceso ´ private no se puede extender la clase. La clase no se instancia con el operador new si no a trav´s e de la llamada a un m´todo que siempre devuelve la misma instancia y unica e ´ instancia de la clase.234 ˜ CAP´ ITULO 16. } public S i n g l e t o n g e t I n s t a n c i a ( ) { i f ( i n s t a n c i a == n u l l ) i n s t a n c i a = new S i n g l e t o n ( ) . por ejemplo nuestra aplicaci´n s´lo conoce una instancia de la clase o o que accede a una impresora. Cuando el hilo que est´ a la espera contin´e a u su ejecuci´n donde qued´ (justo despu´s de comprobar que no hab´ ninguna o o e ıa instancia de Singleton creada).2. antes de ello. Supongamos ahora que se est´n ejecutando simult´neamente dos hilos que a a quieren recuperar una instancia de la clase Singleton. recuperamos la instancia llamando al m´todo getInstancia() e y no con el operador new. crear´ una nueva instancia de la clase Singleton a . y que justo despu´s de evaluar u e la condici´n y antes de crear la instancia en la l´ o ınea 10. de esto modo prohibimos la creaci´n de instancias de esta clase con el operador o new. instancia de la clase Singleton. ahora s´ crea una ı. quien tambi´n eval´a la condici´n de la l´ e u o ınea 9 obteniendo false (ya que la instancia no fue creada por el primer hilo). En este caso. o al sistema de ficheros. Ejemplo de implementaci´n o En el listado 16. pero sirve para documentar la clase.5. Situaci´n que intenta resolver o El patr´n de dise˜o Singleton garantiza que s´lo existe una instancia de una o n o determinada clase. que comprueba la e condici´n de la l´ o ınea 9 y que se eval´a a false. y que. En la l´ ınea 3. definimos una referencia a la propia clase.

Como resultado final nos encontraremos con dos instancias de la misma clase. En este caso. c l a s s ) { i f ( i n s t a n c i a == n u l l ) i n s t a n c i a = new S i n g l e t o n C o n c u r r e n t e ( ) . justo lo que no dese´bamos que ocurriera. 16. a La soluci´n a este problema pasa por sincronizar el bloque de creaci´n de o o la instancia de Singleton tal y como se muestra en el Listado 16. o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public c l a s s S i n g l e t o n C o n c u r r e n t e { private S i n g l e t o n C o n c u r r e n t e i n s t a n c i a = n u l l . o 16. Si o hacemos una primera comprobaci´n fuera del bloque sincronizado y obtenemos o false nunca entraremos en el bloque sincronizado y no caeremos en el sobrecoste temporal que esto implica. Si cada vez que necesitamos una instancia . si no lo est´ la creamos dentro a del bloque sincronizado garantizando que ning´n otro hilo entrar´ en este bloque u a si ya est´ en posesi´n de otro hilo. por ejemplo.6. Supongamos. e escribimos un bloque sincronizado. o siempre tendremos que pugnar por el cerrojo del bloque sincronizado con el consiguiente coste en tiempo de ejecuci´n que esto supone. private S i n g l e t o n C o n c u r r e n t e ( ) { super ( ) .6. Situaci´n que intenta resolver o Tal y como hemos visto en la introducci´n de este cap´ o ıtulo. EL PATRON DE DISENO FACTORY METHOD 235 ya que al no volver a comprobar la condici´n para este hilo sigue siendo v´lido o a que no existe ninguna instancia.6. ya que en este momento garantizamos que s´lo hay un hilo ejecut´ndolo? o a Para evitar el sobrecoste que implica la ejecuci´n de bloques sincronizados. La doble comprobaci´n es para evitar que a o o no ocurra lo mismo que en el caso anterior. inmediatamente despu´s de comprobado si ya hay una instancia creada. el desacoplamiento entre clases muchas veces pasa porque una clase cliente no cree una instancia de otra clase con la que quiera trabajar. Este patr´n de dise˜o es relativamente sencillo y las ventajas que o o n presenta su uso son muchas. que justo despu´s de comprobarla y e antes de entrar en el bloque sincronizado otro hilo gane la carrera y ejecute el bloque sincronizado mientras el primero espera a seguir con la ejecuci´n.´ ˜ 16. Motos y Camiones.1. que estamos creando una aplicaci´n que representa una f´brica de Veh´ o a ıculos pudiendo ser estos Coches. Si eliminamos la comprobaci´n fuera del bloque. El patr´n de dise˜ o Factory Method o n Factory Method es otro patr´n de dise˜o dentro del grupo de patrones de dise˜o o n n de creaci´n.2: Implementaci´n sencilla del patr´n Singleton o o ¿Por qu´ no hacemos una unica comprobaci´n dentro del bloque sincronizae ´ o do. } public S i n g l e t o n C o n c u r r e n t e g e t I n s t a n c i a ( ) { i f ( i n s t a n c i a == n u l l ) synchronized ( S i n g l e t o n C o n c u r r e n t e . } } Listado 16. dentro del cual lo primero que volvemos a comprobar es si la instancia sigue sin estar creada. } return i n s t a n c i a .2.

4.5 y 16. Motos o Camiones. String getDescripcion () .6.3 que es el tipo de datos abstracto para toda clase de Vehiculos. con independencia de si son Coches. PATRONES DE DISENO de un tipo concreto usamos el operador new.6 aparecen las clases concretas para cada uno de los tres tipos de Veh´ ıculos que la f´brica puede crear. } Listado 16. o Una manera de desacoplar la clase cliente. 16. s t a t i c f i n a l i n t MOTO = 2 .2. Moto. s t a t i c f i n a l i n t CAMION = 3 . Cami´n cambie y nuestro o o c´digo deje de funcionar.3: El tipo de datos abstracto Vehiculo En los Listados 16. y las instancias concretas de Coche.236 ˜ CAP´ ITULO 16. Ejemplo de implementaci´n o Primero escribimos un interface del Listado 16. } } Listado 16.6: Clase concreta que representa un Camion Cada una de las clases anteriores da una implementaci´n concreta para el o m´todo getDescripcion(). la que quiere recuperar instancias de Veh´ ıculos concretos.4: Clase concreta que representa un Coche 1 2 3 4 5 6 public c l a s s Moto implements V e h i c u l o { @Override public S t r i n g g e t D e s c r i p c i o n ( ) { return " S o y u n a m o t o " . ´ } } Listado 16. Moto. Este interface cuenta con constantes que identifican a los distintos tipos de veh´ ıculos que se pueden crear. 1 2 3 4 5 6 public i n t e r f a c e V e h i c u l o { s t a t i c f i n a l i n t COCHE = 1 . 16. corremos el riesgo de que la implementaci´n de las clases concretas Coche. Cami´n es o definir una nueva clase encargada de crear las instancias de las clases concretas y devolver las referencias no al tipo concreto si no a un interface o clase abstracta.5: Clase concreta que representa una Moto 1 2 3 4 5 6 public c l a s s Camion implements V e h i c u l o { @Override public S t r i n g g e t D e s c r i p c i o n ( ) { return " S o y u n c a m i o n " . e . } } Listado 16. a 1 2 3 4 5 6 public c l a s s Coche implements V e h i c u l o { @Override public S t r i n g g e t D e s c r i p c i o n ( ) { return " S o y u n c o c h e " .

Veamos un nuevo patr´n de dise˜o que de alg´n o n u modo amplia el patr´n de dise˜o Factory Method. } } Listado 16. o u t .8.MOTO) . default : v e h i c u l o = new Coche ( ) . break . p r i n t l n ( v e h i c u l o . break .6.7 muestra la implementaci´n de la f´brica de veh´ o a ıculos. el cliente no lo percibe. c r e a V e h i c u l o ( V e h i c u l o . System . System .8: Un cliente de la f´brica de veh´ a ıculos Como ves. p r i n t l n ( v e h i c u l o . System . Lo interesante de este cliente es que no crea en ning´n momento una instancia concreta de ninguna clase. g e t D e s c r i p c i o n ( ) ) . o u t . switch ( t i p o ) { case V e h i c u l o . ´ . } return v e h i c u l o .´ ˜ 16. case V e h i c u l o . break . permiti´ndonos la creaci´n o n e o de familias de tipos de datos en vez de un unico tipo de datos.7: La f´brica de veh´ a ıculos Para finalizar. Si o la f´brica de veh´ a ıculos incorpora nuevos veh´ ıculos. break . c r e a V e h i c u l o ( V e h i c u l o . case V e h i c u l o . La f´brica crea la instancia del tipo concreto y la devuelve como una a referencia al tipo abstracto Veh´ ıculo.COCHE) . v e h i c u l o = F a b r i c a V e h i c u l o s . este patr´n de dise˜o es muy util cuando se necesita crear clases o n ´ concretas de un mismo tipo de datos abstracto. que en el ejemplo mostrado era el interface Vehiculo. EL PATRON DE DISENO FACTORY METHOD 237 El Listado 16. g e t D e s c r i p c i o n ( ) ) . c r e a V e h i c u l o ( V e h i c u l o . veamos c´mo un cliente concreto trabaja con esta f´brica de o a veh´ ıculos. el cliente puede utilizarlos.COCHE: v e h i c u l o = new Coche ( ) .CAMION) . v e h i c u l o = F a b r i c a V e h i c u l o s .MOTO: v e h i c u l o = new Moto ( ) . o u t . El cliente se muestra en el Listado 16. p r i n t l n ( v e h i c u l o . de nuevo. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public c l a s s F a b r i c a V e h i c u l o s { public s t a t i c V e h i c u l o c r e a V e h i c u l o ( i n t t i p o ) { Vehiculo vehiculo . o Si la implementaci´n de una clase concreta cambia. g e t D e s c r i p c i o n ( ) ) . o 1 2 3 4 5 6 7 8 9 10 public c l a s s C l i e n t e { public s t a t i c void main ( S t r i n g [ ] a r g s ) { V e h i c u l o v e h i c u l o = F a b r i c a V e h i c u l o s . sin conocer la implementaci´n concreta. Esta clase posee un unico m´todo est´tico que recibe el tipo del veh´ ´ e a ıculo que deseamos obtener. Podr´ ıamos decir que siempre estamos creando instancias del mismo tipo de datos.CAMION: v e h i c u l o = new Camion ( ) . } } Listado 16. si u no que delega la creaci´n de instancias concretas en la clase FabricaVehiculos.

Chasis y Ruedas). imagina esta vez que se intenta describir f´bricas de veh´ a ıculos gen´ricas. Lo que distingue un veh´ ıculo concreto. Motor. tanto si es europea como japonesa a se construyen tres modelos de veh´ ıculos: Turismos. public abstract void d e s c r i p c i o n ( ) .9: Un Veh´ ıculo como abstracci´n de los tres modelos que puede o construir una f´brica Turismos. El patr´n de dise˜ o Abstract Factory o n Este nuevo patr´n de dise˜o tambi´n pertenece al grupo de los patrones de o n e dise˜o de creaci´n. Dos ejemplos de f´bricas de e a veh´ ıculos concretas pueden ser una f´brica de veh´ a ıculos europea y otra f´brica a de veh´ ıculos japonesa. Deportivos. Motor y Ruedas. // p r o t e c t e d E x t r a s e x t r a s . Ruedas y Extras. En los Listados a 16.1. 16. Berlinas y Deportivos a . motores japoneses). motores europeos). Berlinas.7.238 ˜ CAP´ ITULO 16.7. Berlinas y Deportivos.9 a 16. pero esta vez no crea un unico tipo de datos si no que crea n o ´ familias de tipos de datos. 1 2 3 4 5 6 7 public abstract c l a s s V e h i c u l o { // p r o t e c t e d Rueda r u e d a s . mientras que una f´brica japonesa utiliza componentes japoneses (ruedas japonesas. por ejemplo un Turismo creado en una f´bria ca europea o en una japonesa no es el proceso de construcci´n. Ejemplo de implementaci´n o Para ver un ejemplo concreto vamos a empezar describiendo las entidades que forman parte del problema. } Listado 16. que podemos restringir a Turismos. misma gama de productos (Veh´ ıculos) pero construidos con componentes distintos (Motor. hemos a˜adido un m´todo que permite obtener una descripci´n de cada uno de n e o los Vehiculos public void descripcion(). mientras que en Abstract Factory se crea una o gama de productos (Motor.2. Lo que distingue a un Turismo europeo de uno japones es que una f´brica europea de veh´ a ıculos utiliza componentes europeos (ruedas europeas. Vamos a suponer un Turismo est´ formado unicamente por un Chasis y un a ´ Motor.7. En una f´brica. Ambas f´bricas de veh´ a ıculos producen diferentes tipos de veh´ ıculos. Situaci´n que intenta resolver o Siguiendo con el ejemplo de la f´brica de veh´ a ıculos. chasis europeos. // p r o t e c t e d Motor motor . chasis japoa neses. ya que ambos o veh´ ıculos tienen motor. PATRONES DE DISENO 16. La diferencia con el patr´n de dise˜o Factory Mehod (Vehiculo) es que en o n este se crea un s´lo producto. 16. chasis y ruedas.12 se muestra el c´digo para los veh´ o ıculos. // p r o t e c t e d C h a s i s c h a s i s . Chasis y Ruedas). Y finalmente. En la interface Vehiculo. a un Deportivo est´ formado por Chasis. Una Berlina est´ formada por un Chasis. Resumiendo.

....... private Rueda r u e d a s . o u t ...... extras . private E x t r a s e x t r a s . p r i n t l n ( " ....." ) ... } } Listado 16... motor .. } } ..11: Una Berlina es una especializaci´n de un Vehiculo o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public c l a s s D e p o r t i v o extends V e h i c u l o { private C h a s i s c h a s i s . o chasis .....10: Un Turismo es una especializaci´n de un Vehiculo o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public c l a s s B e r l i n a extends V e h i c u l o { private C h a s i s c h a s i s ....... d e s c r i p c i o n ( ) .. private Motor motor .. d e s c r i p c i o n ( ) .... chasis .. System ...... creaChasis ( ) .7. public Turismo ( FabricaComponentes f a b r i c a C o m p o n e n t e s ) { c h a s i s = fabricaComponentes . ruedas = fabricaComponentes .. e x t r a s = fabricaComponentes .. motor = f a b r i c a C o m p o n e n t e s ..... c r e a M o t o r ( ) ... creaExtras ( ) . o chasis ........" ) ." ) . public D e p o r t i v o ( FabricaComponentes f a b r i c a C o m p o n e n t e s ) { ruedas = fabricaComponentes .. ruedas .. } @Override public void d e s c r i p c i o n ( ) { System .´ ˜ 16.D e s c r i p c i ´ n d e u n D E P O R T I V O . c h a s i s = fabricaComponentes . private Motor motor . d e s c r i p c i o n () . p r i n t l n ( " .. o ruedas ... o u t . private Motor motor ......... creaRuedas ( ) ... descripcion () . p r i n t l n ( " ...D e s c r i p c i ´ n d e u n T U R I S M O ... descripcion () . creaChasis ( ) ... } @Override public void d e s c r i p c i o n ( ) { System .... EL PATRON DE DISENO ABSTRACT FACTORY 239 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public c l a s s Turismo extends V e h i c u l o { private C h a s i s c h a s i s ..... motor .. c r e a M o t o r ( ) .. } } Listado 16. d e s c r i p c i o n () . public B e r l i n a ( FabricaComponentes f a b r i c a C o m p o n e n t e s ) { c h a s i s = fabricaComponentes ... o u t .D e s c r i p c i ´ n d e u n a B E R L I N A . motor = f a b r i c a C o m p o n e n t e s ... descripcion () . p r i n t l n ( " . creaRuedas ( ) .... System . creaChasis ( ) ..... System . p r i n t l n ( " . motor . c r e a M o t o r ( ) .. descripcion () ... o u t .. } @Override public void d e s c r i p c i o n ( ) { System ." ) ." ) ." ) .. private Rueda r u e d a s . p r i n t l n ( " .. motor = f a b r i c a C o m p o n e n t e s . o u t .... o u t ... d e s c r i p c i o n ( ) ...

p r i n t l n ( " C h a s i s l i g e r o d e a l u m i n i o . o u t . } Listado 16. o u t . o 1 2 3 4 5 6 7 8 public c l a s s E x t r a s D e p o r t i v o s E s t i l o J a p o n e s implements E x t r a s { @Override public void d e s c r i p c i o n ( ) { System .240 ˜ CAP´ ITULO 16. mientras que los Veh´ o ıculos europeos tienen ruedas de perfil bajo. p e r o a l e s t i l o j a p o n e s . } Listado 16. .12: Un Deportivo es una especializaci´n de un Vehiculo o Vamos ahora a detallar los componentes que forman parte de cada uno de los diferentes Vehiculos. } } .15: Un ChasisReforzado es una especializaci´n de un Chasis que o ser´ utilizado s´lo en la construcci´n de Veh´ a o o ıculos europeos 1 2 3 public i n t e r f a c e E x t r a s { void d e s c r i p c i o n ( ) . los Veh´ ıculos japoneses tienen extras de tipo deportivo japones y los europeos de tipo deportivo. 1 2 3 public i n t e r f a c e C h a s i s { void d e s c r i p c i o n ( ) . El Motor de un Vehiculo japones es siempre de muy bajo consumo y bajas emisiones de CO2. Las Ruedas de un Veh´ ıculo japones son siempre de muy larga duraci´n. o 1 2 3 4 5 6 public c l a s s C h a s i s L i g e r o implements C h a s i s { @Override public void d e s c r i p c i o n ( ) { System . El los listados 16. si es europeo. p r i n t l n ( " C h a s i s r e f o r z a d o " ) .24 se muestra cada uno de los interface y las especializaciones de cada componente que puede formar parte de un Veh´ ıculo.14: Un ChasisLigero es una especializaci´n de un Chasis que o ser´ utilizado s´lo en la construcci´n de Veh´ a o o ıculos japoneses. " ) . . } } Listado 16. o u t . si es europeo su Chasis es siempre reforzado. . el Motor es de alto rendimiento. Y finalmente. " ) .16: Unos Extras como abstracci´n. 1 2 3 4 5 6 public c l a s s C h a s i s R e f o r z a d o implements C h a s i s { @Override public void d e s c r i p c i o n ( ) { System . PATRONES DE DISENO Listado 16.13 a 16.13: Un Chasis como abstracci´n. Si el Veh´ ıculo es japones su Chasis es siempre ligero y de aluminio. } } Listado 16. p r i n t l n ( " E x t r a s d e p o r t i v o s .

19: Un Motor como abstracci´n. o u t . o 1 2 3 4 5 6 7 public c l a s s RuedaLargaDuracion implements Rueda { @Override public void d e s c r i p c i o n ( ) { System .17: Unos ExtrasDeportivosEstiloJapones es una especializaci´n de o unos Extras que ser´n utilizados s´lo en la construcci´n de Veh´ a o o ıculos japoneses 1 2 3 4 5 6 public c l a s s E x t r a s D e p o r t i v o s implements E x t r a s { @Override public void d e s c r i p c i o n ( ) { System . } } Listado 16.22: Una Rueda como abstracci´n. p r i n t l n ( " M o t o r d e a l t o r e n d i m i e n t o . ´ } . } } Listado 16.´ ˜ 16. } } Listado 16. p r i n t l n ( " M o t o r d e m u y b a j o c o n s u m o y b a j a s e m i s i o n e s d e C O 2 .7.") . } Listado 16. p r i n t l n ( " E x t r a s d e p o r t i v o s .20: Un MotorBajoCosumo es una especializaci´n de un Motor que o ser´ utilizado s´lo en la construcci´n de Veh´ a o o ıculos japoneses 1 2 3 4 5 6 public c l a s s Mo torA lto Ren dimi ent o implements Motor { @Override public void d e s c r i p c i o n ( ) { System .21: Un MotorAltoRendimienot es una especializaci´n de un Motor o que ser´ utilizado s´lo en la construcci´n de Veh´ a o o ıculos europeos 1 2 3 public i n t e r f a c e Rueda { void d e s c r i p c i o n ( ) . } Listado 16. o u t . " ) . p r i n t l n ( " R u e d a s d e l a r g a d u r a c i o n " ) . EL PATRON DE DISENO ABSTRACT FACTORY 241 Listado 16.18: Unos ExtrasDeportivos es una especializaci´n de unos Extras que o ser´n utilizados s´lo en la construcci´n de Veh´ a o o ıculos europeos 1 2 3 public i n t e r f a c e Motor { void d e s c r i p c i o n ( ) . " ) . o u t . o 1 2 3 4 5 6 7 8 public c l a s s MotorBajoConsumo implements Motor { @Override public void d e s c r i p c i o n ( ) { System . o u t .

} } Listado 16. o u t . Las f´bricas de coma a ponentes son las encargadas de crear cada uno de los componentes que forman un Veh´ ıculo dependiendo de si estamos en Europa o Jap´n.26: Una FabricaComponentesJaponesa es una especializaci´n de una o FabricaComponentes que crea los distintos componentes para cada tipo de Veh´ ıculos japoneses 1 2 3 public c l a s s FabricaComponentesEuropea implements FabricaComponentes { @Override . Los listados 16.25: Una FabricaComponentes como abstracci´n. vamos a utilizar el patr´n de dise˜o Factory Method.242 8 ˜ CAP´ ITULO 16. " ) . } @Override public E x t r a s c r e a E x t r a s ( ) { return new E x t r a s D e p o r t i v o s E s t i l o J a p o n e s ( ) . PATRONES DE DISENO } Listado 16.23: Una RuedaLargaDuracion es una especializaci´n de una Rueda o que ser´ utilizada s´lo en la construcci´n de Veh´ a o o ıculos japoneses 1 2 3 4 5 6 7 8 public c l a s s R u e d a P e r f i l B a j o implements Rueda { @Override public void d e s c r i p c i o n ( ) { System . } @Override public C h a s i s c r e a C h a s i s ( ) { return new C h a s i s L i g e r o ( ) . } Listado 16. o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public c l a s s F a b r i c a C o m p o n e n t e s J a p o n e s a implements FabricaComponentes { @Override public Rueda c r e a R u e d a s ( ) { return new RuedaLargaDuracion ( ) .24: Una RuedaPerfilBajo es una especializaci´n de una Rueda que o ser´ utilizada s´lo en la construcci´n de Veh´ a o o ıculos europeos Es el momento de construir las f´bricas de componentes. } } Listado 16. Para implementaro las. p r i n t l n ( " R u e d a d e p e r f i l b a j o . } @Override public Motor c r e a M o t o r ( ) { return new MotorBajoConsumo ( ) . o a 1 2 3 public i n t e r f a c e Rueda { void d e s c r i p c i o n ( ) .27 muestran el c´digo para cada una de las f´bricas de componentes.25 a o n 16.

. . v e h i c u l o = new D e p o r t i v o ( f a b r i c a C o m p o n e n t e s ) . la japonesa y la europea en los listados 16.28: Una FabricaVehiculos como abstracci´n. } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 . v e h i c u l o = new Turismo ( f a b r i c a C o m p o n e n t e s ) . o u t . break . " ) . . } @Override public E x t r a s c r e a E x t r a s ( ) { return new E x t r a s D e p o r t i v o s ( ) . o u t . . } Listado 16. break . case DEPORTIVO: System . break . default : System . . p r i n t l n ( " F a b r i c a n d o u n d e p o r t i v o j a p o n e s . p r i n t l n ( " F a b r i c a n d o u n a b e r l i n a j a p o n e s a . . 1 2 3 public i n t e r f a c e F a b r i c a V e h i c u l o s { Vehiculo creaVehiculo ( TipoVehiculo tipoVehiculo ) . o u t . v e h i c u l o = new Turismo ( f a b r i c a C o m p o n e n t e s ) . . la implementaci´n de cada una de o n ´ o las f´bricas de veh´ a ıculos.7. o u t .´ ˜ 16. v e h i c u l o = new B e r l i n a ( f a b r i c a C o m p o n e n t e s ) .28 al 16. } @Override public C h a s i s c r e a C h a s i s ( ) { return new C h a s i s R e f o r z a d o ( ) . p r i n t l n ( " F a b r i c a n d o u n t u r i s m o j a p o n e s . EL PATRON DE DISENO ABSTRACT FACTORY 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 243 public Rueda c r e a R u e d a s ( ) { return new R u e d a P e r f i l B a j o ( ) . } return v e h i c u l o . case BERLINA : System .27: Una FabricaComponentesEuropea es una especializaci´n de una o FabricaComponentes que crea los distintos componentes para cada tipo de Veh´ ıculos europeos Ya nos encontramos en la recta final para acabar de ver la implementaci´n o de este patr´n de dise˜o. } @Override public Motor c r e a M o t o r ( ) { return new Mo torA lto Ren dimi ent o ( ) . } } Listado 16. p r i n t l n ( " F a b r i c a n d o u n t u r i s m o j a p o n e s . break . switch ( t i p o V e h i c u l o ) { case TURISMO: System . " ) . o public c l a s s F a b r i c a V e h i c u l o s J a p o n e s a implements F a b r i c a V e h i c u l o s { @Override public V e h i c u l o c r e a V e h i c u l o ( T i p o V e h i c u l o t i p o V e h i c u l o ) { FabricaComponentes f a b r i c a C o m p o n e n t e s = new F a b r i c a C o m p o n e n t e s J a p o n e s a () . " ) . Vemos por ultimo. . " ) . Vehiculo vehiculo .30.

PATRONES DE DISENO } Listado 16. del grupo de patrones de o comportamiento. combo-box. a 16. digamos por caso. p r i n t l n ( " F a b r i c a n d o u n a b e r l i n a e u r o p e a . etc´tera). o u t . p r i n t l n ( " F a b r i c a n d o u n t u r i s m o e u r o p e o . . p r i n t l n ( " F a b r i c a n d o u n d e p o r t i v o e u r o p e o . . . . se crean botones o distintos si la f´brica de componentes es. de modo que.244 33 ˜ CAP´ ITULO 16. p r i n t l n ( " F a b r i c a n d o u n t u r i s m o e u r o p e o . o u t . } } Listado 16. v e h i c u l o = new Turismo ( f a b r i c a C o m p o n e n t e s ) . break .8. . de los dos que vamos a ver. break . v e h i c u l o = new Turismo ( f a b r i c a C o m p o n e n t e s ) . es la f´brica de veh´ a ıculos japonesa la que se provee de componentes japoneses y la f´brica europea la que se provee de componentes europeos. break . " ) .29 y 16. .30 est´ en la l´ e a ınea 5 de ambos listados. . switch ( t i p o V e h i c u l o ) { case TURISMO: System . case BERLINA : System . v e h i c u l o = new B e r l i n a ( f a b r i c a C o m p o n e n t e s ) . } return v e h i c u l o . a Otro ejemplo que com´nmente se utiliza como ejemplo del patr´n de dise˜o u o n Abstract Factory es la programaci´n de un framework para componer ventanas o en distintos sistemas operativos. El patr´n de dise˜ o Strategy o n Este patr´n es el primero. o u t . " ) . " ) . default : System . Las ventanas que queremos crear est´n formaa das por el mismo tipo de componentes (botones.29: Una FabricaVehiculosJaponesa es una especializaci´n de una o FabricaVehiculos que crea los distintos tipos de Veh´ ıculos japoneses 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public c l a s s F a b r i c a V e h i c u l o s E u r o p e a implements F a b r i c a V e h i c u l o s { @Override public V e h i c u l o c r e a V e h i c u l o ( T i p o V e h i c u l o t i p o V e h i c u l o ) { FabricaComponentes f a b r i c a C o m p o n e n t e s = new FabricaComponentesEuropea () .30: Una FabricaVehiculosEuropea es una especializaci´n de una o FabricaVehiculos que crea los distintos tipos de Veh´ ıculos europeos El detalle de inter´s en los listados 16. break . " ) . Vehiculo v e h i c u l o = null . por ejemplo. listas. . v e h i c u l o = new D e p o r t i v o ( f a b r i c a C o m p o n e n t e s ) . case DEPORTIVO: System . o u t . e pero quien proporciona los componentes es el sistema operativo sobre el que se vaya a ejecutar la aplicaci´n. Mac OS X que si la a f´brica es Linux. .

en la mayor´ de las ocasioıa nes existe m´s de un algoritmo para encontrar la soluci´n. ordenar o una secuencia de elemento teniendo en cuenta cierta funci´n de comparaci´n o o entre ellos. o 1 2 3 public c l a s s C o n t a d o r D e s c e n d e n t e implements Contador { @Override .31: Este es el comportamiento com´n a todos los algoritmo: Contar u 1 2 3 4 5 6 7 8 9 10 11 public c l a s s C o n t a d o r A s c e n d e n t e implements Contador { @Override public S t r i n g c u e n t a ( ) { S t r i n g cuenta = " " . s t a t i c f i n a l i n t IMPARES = 4 . todos ellos van a implementar el interface que se muestra en el listado 16. S t r i n g cuenta ( ) . F´ o u ıjate que en los cuatros casos anteriores el algoritmo es el mismo: Contar n´meros. c u e n t a += i + " . } Listado 16. 1 2 3 4 5 6 7 8 public i n t e r f a c e Contador { s t a t i c f i n a l i n t ASCENDENTE = 1 .8.8. Piensa por ejemplo a o en los algoritmos de ordenaci´n. La codificaci´n m´s flexible ser´ aquella que permita intercambiar el algoo a a ritmo de ordenaci´n con el m´ o ınimo. el objetivo de todos ellos es el mismo.1. Situaci´n que intenta resolver o Cuando intentamos resolver un problema concreto. return c u e n t a . } } i ++) Listado 16. s t a t i c f i n a l i n t DESCENDENTE = 2 . Ejemplo de implementaci´n o Como ejemplo de implementaci´n. 16.31.´ ˜ 16. s t a t i c f i n a l i n t PARES = 3 . supongamos que nuestro algoritmo cuenta o n´meros naturales. i < 10. u Para hacer los algoritmos intercambiables. el algoritmo de la burbuja o el algoritmo quicksort. o nulo. impacto sobre la aplicaci´n. Para ordenar una secuencia de n´meros naturales podemos u u utilizar el algoritmo de intercambio.8.32 al 16.35. El o patr´n Strategy nos dice que debemos encapsular cada algoritmo dentro de una o clase y hacer estas clases intercambiables para el cliente que las use de modo transparente. Las cuatro implementaciones de contadores particulares se muestran en los Listados 16. tomando un caso sencillo podemos concretar que los elementos son n´meros naturales. " . Existir´n casos en los que nos interese contar de modo asu a cendente y otros casos en los que nos interese contar de modo descendente.32: Implementaci´n de un contador ascendente.2. Incluso puede que a veces nos interese contar de modo ascendente s´lo n´meo u ros pares o s´lo n´meros impares. EL PATRON DE DISENO STRATEGY 245 16. for ( int i = 0 .

cuenta ( ) . o 1 2 3 4 5 6 7 8 9 10 11 12 13 public c l a s s C o n t a d o r I m p a r e s implements Contador { @Override public S t r i n g c u e n t a ( ) { S t r i n g cuenta = " " .36: 1 2 3 4 5 6 7 8 9 10 11 12 13 import c o n t a r . public void c u e n t a ( ) { contador . o u 1 2 3 4 5 6 7 8 9 10 11 12 13 public c l a s s C o n t a d o r P a r e s implements Contador { @Override public S t r i n g c u e n t a ( ) { S t r i n g cuenta = " " . i >= 0 . } } i += 2 ) Listado 16.34: Implementaci´n de un contador de n´meros impares. " .246 4 5 6 7 8 9 10 11 12 13 ˜ CAP´ ITULO 16. PATRONES DE DISENO public S t r i n g c u e n t a ( ) { S t r i n g cuenta = " " . for ( int i = 1 . return c u e n t a . } } Listado 16. Contador . return c u e n t a .36: Un cliente que puede utilizar cualquiera de los anteriores algoritmo para contar. c u e n t a += i + " . } } i += 2 ) Listado 16. " . " .33: Implementaci´n de un contador descendente. i −−) c u e n t a += i + " . o u Ahora escribamos un cliente que pueda utilizar estos algoritmos de modo intercambiable. i < 10. return c u e n t a . i < 10. for ( int i = 0 .35: Implementaci´n de un contador de n´meros pares. contador = contador . } } Listado 16. c u e n t a += i + " . tal y como muestra el Listado 16. f o r ( i n t i = 9 . public c l a s s C l i e n t e { private Contador c o n t a d o r . . } public void s e t C o n t a d o r ( Contador c o n t a d o r ) { this .

s e t C o n t a d o r (new C o n t a d o r I m p a r e s ( ) ) . A esta t´cnica e e e de relaci´n entre clase se le llama Inyecci´n de Dependencias o Inversi´n de o o o Control. el Listado 16. Este comportamiento se conoce como Principio de Hollywood que se puede resumir en la frase No me llames. . cuenta ( ) . 16. o n . es interrogar o cada cierto tiempo por el estado de ese atributo. e j e c u t a ( ) . c l i e n t e . cuenta ( ) . y altamente ineficiente. de un atributo en una determinada instancia. c l i e n t e . } } args ) { Listado 16. a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import import import import contar contar contar contar . ContadorDescendente . c l i e n t e . Lo hemos utilizado amo n pliamente en el cap´ ıtulo 11 dedicado a la programaci´n de interfaces gr´ficos de o a usuario. EL PATRON DE DISENO OBSERVER 247 Esta clase Cliente tiene una caracter´ ıstica interesante para poder utilizar cualquier tipo de algoritmo para contar. los escuchadores para un compoo a nente gr´fico. s e t C o n t a d o r (new C o n t a d o r D e s c e n d e n t e ( ) ) . por ejemplo un bot´n. c l i e n t e . ContadorImpares . c l i e n t e . public c l a s s P r i n c i p a l { private void e j e c u t a ( ) { C l i e n t e c l i e n t e = new C l i e n t e ( ) . si no que espera a que la instancia monitorizada le avise del cambio. Y este es. ContadorPares . c l i e n t e . ya te llamar´ yo.´ ˜ 16.9. el algoritmo particular se le inyecta a trav´s del m´todo public void setContador(Contador contador). Es m´s sencillo que sea la propia instancia quien nos avise de que su atributo a ha cambiado de valor. cuenta ( ) . el patr´n de dise˜o Observer. 16. cuenta ( ) . Lo que hac´ a o ıamos era escribir un escuchador que era notificado cada vez que ocurr´ un evento sobre el bot´n.37 muestra c´mo utio lizar la clase Cliente inyect´ndole los cuatro tipos de contadores. no es el cliente el que consulta. s e t C o n t a d o r (new C o n t a d o r P a r e s ( ) ) . c l i e n t e . e Recuerda c´mo program´bamos. El patr´n de dise˜ o Observer o n Observer es otro patr´n de dise˜o de comportamiento. la opci´n directa.37: Podemos cambiar din´micamente el tipo de contador que utiliza a la clase Cliente. ContadorAscendente . en Swing. } public s t a t i c void main ( S t r i n g [ ] new P r i n c i p a l ( ) .9. . . Situaci´n que intenta resolver o Cuando intentamos monitorizar el estado. c l i e n t e . preıa o cisamente.9. Finalmente. La ineficiencia de este m´todo e se debe a que aunque no cambie el estado del atributo. y por completar el ejemplo. s e t C o n t a d o r (new C o n t a d o r A s c e n d e n t e ( ) ) .1. estamos consumiendo tiempo en averiguar si lo ha hecho. por ejemplo.

y quien recibe los informes son sus ıa. add ( o b s e r v a d o r ) . Ejemplo de implementaci´n o Como ejemplo. A r r a y L i s t . o Los Listados 16. } @Override public void removeObservador ( O b s e r v a d o r o b s e r v a d o r ) { o b s e r v a d o r e s . } @Override public void i n f o r m a O b s e r v a d o r e s ( S t r i n g a c c i o n ) { for ( Observador observador : o b s e r v a d o r e s ) o b s e r v a d o r .9. PATRONES DE DISENO 16. public c l a s s EspiaKGB implements Observado { private S t r i n g nombre .39 muestran el c´digo referente al esp´ o ıa. t h i s . n o o eliminarlos cuando acaba su misi´n. nombre = nombre .248 ˜ CAP´ ITULO 16. Los Listados 16. public EspiaKGB ( S t r i n g nombre ) { super ( ) .41 muestran el c´digo relativo a los jefes. El KGB tiene esp´ que informan de todos ıa. i n f o r m e ( nombre + " : " + a c c i o n ) . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import j a v a .39: Esta es la clase que representa a un esp´ ıa.38 y 16. ıa a superiores que act´an como observadores. Es a trav´s del m´todo informaObservadores(String accion) por el que el e e esp´ env´ los informes a todos y cada uno de sus jefes. los mantiene en un lista donde puede a˜adir nuevos jefes para informar cuando inicia una misi´n. } Listado 16.40 y ıa ıa 16. u ıa ıas sus movimientos a sus superiores. Quien genera los informes (eventos) es el esp´ el esp´ est´ siendo observado. escribamos una peque˜a novela de esp´ basada en la guerra n ıas fr´ cuando a´n exist´ el KGB. 1 2 3 4 5 public i n t e r f a c e Observado { public void addObservador ( O b s e r v a d o r o b s e r v a d o r ) . import j a v a . remove ( o b s e r v a d o r ) . o . Y un esp´ conoce en e ıa todo momento quienes son los jefes para los que trabaja. } } Listado 16. private L i s t <Observador>o b s e r v a d o r e s = new A r r a y L i s t <Observador >() . u t i l . u t i l . Para que los superiores de un esp´ u ıa reciban mensajes establecen el mecanismo de que el esp´ haga una llamada al ıa m´todo informaObservadores(String accion) de sus jefes. Un mismo esp´ puede trabajar para m´s de ıa a un superior.38: Esta interface es una abstracci´n del comportamiento com´n o u a todos los esp´ ıas. L i s t . el mismo esp´ puede estar trabajando al mismo tiempo para su ıa jefe directo y para el ministerio del interior.2. } @Override public void addObservador ( O b s e r v a d o r o b s e r v a d o r ) { o b s e r v a d o r e s . public void i n f o r m a O b s e r v a d o r e s ( S t r i n g a c c i o n ) . public void removeObservador ( O b s e r v a d o r o b s e r v a d o r ) .

e s p i a B o r i s . } public s t a t i c void main ( S t r i n g [ ] new P r u e b a E s p i a s ( ) . nombre = " A n ´ n i m o " . } Listado 16.io de entrada/salida en Java. este patr´n es ampliamente utilizado Java. . public JefeEspiasKGB ( ) { super ( ) .42: Cada vez que Boris realiza una acci´n informa a sus superiores. Obs e r v a d o r m i n i s t r o D e f e n s a U R S S = new JefeEspiasKGB ( " M i n i s t e r i o d e l interior " ) .41: Esta es la clase que representa a un jefe de esp´ ıa. } } args ) { Listado 16. EL PATRON DE DISENO DECORATOR 249 1 2 3 public i n t e r f a c e O b s e r v a d o r { public void i n f o r m e ( S t r i n g e v e n t o ) . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public c l a s s JefeEspiasKGB implements O b s e r v a d o r { private S t r i n g nombre . } } Listado 16.´ ˜ 16. nombre = nombre .40: Esta interface es una abstracci´n del comportamiento com´n o u a todos los jefes. e j e c u t a ( ) . addObservador ( m i n i s t r o D e f e n s a U R S S ) . } @Override public void i n f o r m e ( S t r i n g e v e n t o ) { System . o Y este es el resultado de su ejecuci´n: o Jefe de Boris recibe de Boris: Estoy siguiendo al topo Ministerio del interior recibe de Boris: Estoy siguiendo al topo 16. o } public JefeEspiasKGB ( S t r i n g nombre ) { super ( ) . Obs e r v a d o r j e f e B o r i s K G B = new JefeEspiasKGB ( " J e f e d e B o r i s " ) . informaObservadores ( " Estoy s i g u i e n d o al topo " ) . e s p i a B o r i s .42 escribimos una sencill´ ısima novela de esp´ ıas. o u t . Y finalmente en el Listado 16. en este caso en el paquete o java java.10. El patr´n de dise˜ o Decorator o n Este es el unico patr´n de dise˜o estructural que vamos a ver. t h i s . p r i n t l n ( nombre + " r e c i b e d e " + e v e n t o ) . Igual que el patr´n ´ o n o Observer. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public c l a s s P r u e b a E s p i a s { private void e j e c u t a ( ) { Observado e s p i a B o r i s = new EspiaKGB ( " B o r i s " ) . addObservador ( j e f e B o r i s K G B ) . e s p i a B o r i s .10.

45. private f l o a t p r e c i o . La idea del patr´n de dise˜o Decorator es tomar una clase base e ir a˜adi´ndoo n n e le nuevas caracter´ ısticas sin utilizar exclusivamente la herencia. sobre el coche n b´sico podemos elegir pintura metalizada o aire acondicionado. otra para el coche b´sico con pintura metalizada. Situaci´n que intenta resolver o Hemos visto algunos ejemplos de este patr´n en las clases de entrada/salida. 16.43 a 16. this . a En algunos casos necesitamos a˜adir nuevas caracter´ n ısticas a nuestras clases pero el uso directo de la herencia dispara exponencialmente el n´mero de clases u que tendr´ ıamos que implementar. Ve´moslo con un ejemplo. d es cri pc ion = d esc ri pci on . this . } public V e h i c u l o ( S t r i n g d e s c r i p c i o n .1. } float precio ) { . Por ejemplo.10. una tercera clase hija para el caso en que alg´n cliente quiera a˜adir aire u n acondicionado y pintura metalizada al coche b´sico. Ejemplo de implementaci´n o Como ejemplo de implementaci´n vamos a utilizar una peque˜a modificaci´n o n o del ejemplo expuesto en la secci´n anterior. Abstraigamos la idea de un Veh´ ıculo como una clase abstracta de la que Coche y Cami´n ser´n dos clases concretas. precio = precio . tales como aire acondia n cionado o pintura metalizada. tal y como muestran los Listados o a 16. Supongamos que a estamos desarrollando una aplicaci´n para un concesionario de coches. o cuando ´ ıbamos recubriendo una clase de partida con nuevas clases hasta alcanzar una clase con la funcionalidad que necesit´bamos. Lo que necesitamos es que cada uno de los extras se a˜ada sobre la clase n base de manera independiente del resto de los extras. y f´ ıjate que no por ello dejamos de tener un veh´ ıculo. y este precio se incrementa cuando el a comprador va a˜adiendo nuevos extras al coche.250 ˜ CAP´ ITULO 16. El coche o b´sico de cada serie tiene un precio. Claramente el uso de la a herencia no es buena idea en este caso.10. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public abstract c l a s s V e h i c u l o { private S t r i n g d e s c r i p c i o n . public V e h i c u l o ( ) { super ( ) .2. un concesionario que quiere calcular o el precio final de los veh´ ıculos que vende pudiendo ser estos coches o camiones. y como a no. super ( ) . Si cada extra a estuviese codificado como una nueva clase que extiende a la clase que representa el coche b´sico deber´ a ıamos escribir una nueva clase para el coche b´sico con a aire acondicionado. PATRONES DE DISENO 16. } public S t r i n g g e t D e s c r i p c i o n ( ) { return d e s c r i p c i o n . } public f l o a t g e t P r e c i o ( ) { return p r e c i o . Al veh´ ıculo b´sico el comprador le puede a˜adir extras.

public V e h i c u l o C o n E x t r a s ( V e h i c u l o v e h i c u l o ) { super ( ) .48 se muestran las clases que a˜aden extras a los n Veh´ ıculos base.43: Abstracci´n de un Veh´ o ıculo.45: Un Cami´n como clase concreta que extiende a Veh´ o ıculo.46: Abstraci´n de un Veh´ o ıculo que a˜ade equipamiento extra. EL PATRON DE DISENO DECORATOR 23 251 } Listado 16.46 a 16. n 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public c l a s s V e h i c u l o C o n A i r e A c o n d i c i o n a d o extends V e h i c u l o C o n E x t r a s { public V e h i c u l o C o n A i r e A c o n d i c i o n a d o ( V e h i c u l o v e h i c u l o ) { super ( v e h i c u l o ) . } @Override public f l o a t g e t P r e c i o ( ) { return v e h i c u l o . 1 2 3 4 5 public c l a s s Camion extends V e h i c u l o { public Camion ( S t r i n g d e s c r i p c i o n .´ ˜ 16. La clase que decora a Veh´ ıculo es VehiculoConExtras y es ella quien resuelve de una manera elegante el problema. f l o a t p r e c i o ) { super ( d e s c r i p c i o n . 1 2 3 4 5 public c l a s s Coche extends V e h i c u l o { public Coche ( S t r i n g d e s c r i p c i o n . g e t P r e c i o ( ) + 3 0 0 . g e t D e s c r i p c i o n ( ) + " .10. this . } } Listado 16. } } Listado 16.44: Un Coche como clase concreta que extiende a Veh´ ıculo. 1 2 3 4 5 6 7 8 public abstract c l a s s V e h i c u l o C o n E x t r a s extends V e h i c u l o { protected V e h i c u l o v e h i c u l o . } @Override public S t r i n g g e t D e s c r i p c i o n ( ) { return v e h i c u l o . p r e c i o ) . vehiculo = vehiculo . por una parte extiende a Veh´ ıculo ya que un VehiculoConExtras sigue siendo un Veh´ ıculo.47: Un Veh´ ıculo que a˜ade el extra aire acondicionado. e En los Listados 16. f l o a t p r e c i o ) { super ( d e s c r i p c i o n . } } Listado 16. 6 7 f . a i r e a c o n d i c i o n a d o " . . } } Listado 16. y por otra parte contiene una referencia al Veh´ ıculo que decora para poder delegar la llamada a sus m´todos. n 1 2 3 public c l a s s V e h i c u l o C o n P i n t u r a M e t a l i z a d a extends V e h i c u l o C o n E x t r a s { public V e h i c u l o C o n P i n t u r a M e t a l i z a d a ( V e h i c u l o v e h i c u l o ) { super ( v e h i c u l o ) . p r e c i o ) .

´ getPrecio () ) . g e t D e s c r i p c i o n ( ) ) .252 4 5 6 7 8 9 10 11 12 13 14 15 ˜ CAP´ ITULO 16. 2 0 0 0 0 ) . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public c l a s s P r u e b a D e c o r a t o r { private void e j e c u t a ( ) { V e h i c u l o v e h i c u l o = new Coche ( " B e r l i n a " . p i n t u r a m e t a l i z a d a " . } @Override public f l o a t g e t P r e c i o ( ) { return v e h i c u l o . g e t D e s c r i p c i o n ( ) ) . n Y finalmente el Listado 16. g e t P r e c i o ( ) + 6 0 0 .49 muestra c´mo utilizar las clases decoradoras o para un par de Veh´ ıculos. v e h i c u l o = new Camion ( " T r a n s p o r t e " . System . v e h i c u l o = new V e h i c u l o C o n A i r e A c o n d i c i o n a d o ( v e h i c u l o ) . o u t . Escribe una aplicaci´n donde sea posible intercambiar de forma sencilla o cada uno de los algoritmos de ordenaci´n. } } Listado 16. g e t D e s c r i p c i o n ( ) + " . Ejercicios. Escribe una aplicaci´n para calcular el precio de un caf´.12 Berlina. e j e c u t a ( ) . o 2. v e h i c u l o = new V e h i c u l o C o n P i n t u r a M e t a l i z a d a ( v e h i c u l o ) . e . } } Listado 16. pintura metalizada El precio de este cami´n es: 100300. o u t . p r i n t l n ( " E l p r e c i o d e e s t e c o c h e e s : " + v e h i c u l o . System . System . leche condesada o el toque de alg´n licor. El resultado de la ejecuci´n de este ejemplo es: o El precio de este coche es: 20901. p r i n t l n ( " E l p r e c i o d e e s t e c a m i o n e s : " + v e h i c u l o . p r i n t l n ( v e h i c u l o . PATRONES DE DISENO } @Override public S t r i n g g e t D e s c r i p c i o n ( ) { return v e h i c u l o . 4 5 f .67 o Transporte. Al caf´ se le o e e puede a˜adir una pizca de leche. aire acondicionado Tanto el precio como la descripci´n de cada veh´ o ıculo se obtienen a partir de la clase base y las clases que van decorando a esta clase base. p r i n t l n ( v e h i c u l o . aire acondicionado. o u t . g e t P r e c i o () ) . System . o u t .49: Ejemplo de creaci´n de un par de Veh´ o ıculos con algunos extras. v e h i c u l o = new V e h i c u l o C o n A i r e A c o n d i c i o n a d o ( v e h i c u l o ) . } public s t a t i c void main ( S t r i n g [ ] a r g s ) { new P r u e b a D e c o r a t o r ( ) . 1. el precio final depende del n´mero de antojos a˜adidos al u n caf´ base. 1 0 0 0 0 0 ) . n u Evidentemente.48: Un Veh´ ıculo que a˜ade el extra pintura metalizada.

´ ˜ 16. los libro de la colecci´n Head first son de una muy clara exo posici´n. En particular la referencia [9] sobre patrones de dise˜os es casi de obligada lectura. n . EL PATRON DE DISENO DECORATOR 253 Lecturas recomendadas.10. El libro de referencia para los patrones de dise˜o es el escrito por The n gang of four del que existe traducci´n al espa˜ol [8]. la manera de presentar los contenidos es muy did´ctica y los o a ejemplos utilizados claros y representativos. o n De nuevo.

PATRONES DE DISENO .254 ˜ CAP´ ITULO 16.

d i r } " /> </ path> 255 . d i r } / t x t " /> 18 < !−− D i r e c t o r i o p a r a l o s i n f o r m e s en f o r m a t o xml −− > 19 <p r o p e r t y name=" r e p o r t s . t x t . d i r " l o c a t i o n=" r e p o r t s " /> 16 < !−− D i r e c t o r i o p a r a l o s i n f o r m e s en f o r m a t o t e x t o −− > 17 <p r o p e r t y name=" r e p o r t s . c l a s s e s . d i r " l o c a t i o n=" / U s e r s / o s c a r / O s c a r / S o f t w a r e / e c l i p s e H e l i o s S E 6 4 / p l u g i n s / o r g . j a r " /> 1 2 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 <p r o p e r t y name=" j u n i t . / l i b " /> 14 < !−− D i r e c t o r i o de i n f o r m e s −− > 15 <p r o p e r t y name=" r e p o r t s . / t e s t / t e s t " /> 10 < !−− S u b d i r e c t o r i o de l a s c l a s e s c o m p i l a d a s de prueba −− > 11 <p r o p e r t y name=" t e s t . c o m p i l e . j a r " /> <p a t h e l e m e n t l o c a t i o n=" $ { b u i l d . n a m e " v a l u e=" C o n v e r s o r T e m p e r a t u r a s . v 4 _ 8 _ 1 _ v 2 0 1 0 0 4 2 7 . . d i r } / h t m l " /> 22 < !−− D i r e c t o r i o p a r a l a d o c u m e n t a c i o n −− > 23 <p r o p e r t y name=" r e p o r t s . d i r " l o c a t i o n=" $ { r e p o r t s . d i r " l o c a t i o n=" .xml <p r o j e c t name=" C o n v e r s i o n T e m p e r a t u r a s " d e f a u l t=" t e s t "> < !−− D i r e c t o r i o d e l c o d i g o f u e n t e −− > 3 <p r o p e r t y name=" s r c . 8 . d i r " l o c a t i o n=" d i s t " /> 26 < !−− Nombre d e l f i c h e r o empaquetado −− > 27 <p r o p e r t y name=" d i s t . v 2 0 0 9 0 5 0 1 0 7 1 0 0 0 . d i r " l o c a t i o n=" b u i l d " /> 6 < !−− S u b d i r e c t o r i o de l a s c l a s e s c o m p i l a d a s d e l p r o y e c t o −− > 7 <p r o p e r t y name=" b u i l d . c l a s s e s . j a r " /> < f i l e s e t d i r=" / U s e r s / o s c a r / O s c a r / S o f t w a r e / e c l i p s e H e l i o s S E 6 4 / p l u g i n s " i n c l u d e s=" o r g . d i r } / c l a s s e s " /> 8 < !−− D i r e c t o r i o de l a s c l a s e s de prueba −− > 9 <p r o p e r t y name=" t e s t . . x m l . d i r " l o c a t i o n=" $ { r e p o r t s . c o m p i l e . c l a s s p a t h "> < f i l e s e t d i r=" $ { l i b } " i n c l u d e s=" * . d i r " l o c a t i o n=" .1 1 0 0 " /> <path i d=" j u n i t "> < f i l e s e t d i r=" $ { j u n i t . / e x c e p c i o n e s " /> 4 < !−− D i r e c t o r i o de c l a s e s c o m p i l a d a s −− > 5 <p r o p e r t y name=" b u i l d . d i r } / t e s t . c l a s s e s . d i r } " i n c l u d e s=" * . d i r " l o c a t i o n=" $ { r e p o r t s . j a v a d o c " l o c a t i o n=" $ { r e p o r t s .Ap´ndice A e build. 1 . c l a s s p a t h " /> <p a t h e l e m e n t path=" $ { t e s t . h a m c r e s t . d i r } / j a v a d o c " /> 24 < !−− D i r e c t o r i o p a r a e l f i c h e r o empaquetado −− > 25 <p r o p e r t y name=" d i s t . j u n i t _ 4 . d i r } / x m l " /> 20 < !−− D i r e c t o r i o p a r a l o s i n f o r m e s en f o r m a t o html −− > 21 <p r o p e r t y name=" r e p o r t s . . c l a s s p a t h "> <path r e f i d=" t e s t . c l a s s e s .c l a s s e s " / > 12 < !−− D i r e c t o r i o de b i b l i o t e c a s d e l p r o y e c t o −− > 13 <p r o p e r t y name=" l i b " l o c a t i o n=" . h t m l . 0 . 1 . d i r " l o c a t i o n=" $ { b u i l d . j a r " /> <f i l e l i s t > </ f i l e l i s t > </ path> < !−− Path p a r a c o m p i l a r l a s c l a s e s de prueba −− > <path i d=" t e s t . d i r " l o c a t i o n=" $ { b u i l d . c o r e _ 1 . d i r } " /> </ path> < !−− Path p a r a e j e c u t a r l a s c l a s e s de prueba −− > <path i d=" t e s t .

d i r } "> <i n c l u d e name=" * * / T e s t * . t x t . "> <mkdir d i r=" $ { t e s t . f a i l u r e s " message=" S e h a n p r o d u c i d o e r r o r e s e n l o s t e s t s .t e s t s " d e s c r i p t i o n=" E j e c u t a l o s t e s t s u n i t a r i o s "> <mkdir d i r=" $ { r e p o r t s . d i r } " /> <d e l e t e d i r=" $ { b u i l d . d i r } " /> < j u n i t printsummary=" t r u e " h a l t o n f a i l u r e=" f a l s e " f a i l u r e p r o p e r t y=" t e s t . d i r } " /> <mkdir d i r=" $ { r e p o r t s . d i r } " /> </ t a r g e t> <t a r g e t name=" c o m p i l e . x m l .XML <t a r g e t name=" c l e a n " d e s c r i p t i o n=" L i m p i a e l p r o y e c t o "> <d e l e t e d i r=" $ { d i s t . x m l . d i r } " /> <d e l e t e d i r=" $ { r e p o r t s . x m l . d i r } " /> </ j u n i t> </ t a r g e t> <t a r g e t name=" t e s t . f a i l u r e s "> <c l a s s p a t h r e f i d=" t e s t . d i r } " /> </ t a r g e t> <t a r g e t name=" c o m p i l e " d e s c r i p t i o n=" C o m p i l a e l p r o y e c t o "> <mkdir d i r=" $ { b u i l d .256 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 ´ APENDICE A. f a i l u r e s "> <c l a s s p a t h r e f i d=" t e s t . c l a s s e s . BUILD.t e s t s " depends=" c o m p i l e " d e s c r i p t i o n=" C o m p i l a l o s t e s t s . x m l " /> </ f i l e s e t> <r e p o r t f o r m a t=" f r a m e s " t o d i r=" $ { r e p o r t s . d i r } " /> < j u n i t printsummary=" t r u e " h a l t o n f a i l u r e=" f a l s e " f a i l u r e p r o p e r t y=" t e s t . d i r } " /> </ j u n i t r e p o r t> < f a i l i f =" t e s t . x m l . c l a s s p a t h " /> <c l a s s p a t h r e f i d=" j u n i t " /> <f o r m a t t e r t y p e=" x m l " /> <b a t c h t e s t t o d i r=" $ { r e p o r t s . d i r } "> < f i l e s e t d i r=" $ { r e p o r t s . c l a s s e s . d i r } " d e s t d i r=" $ { t e s t . c l a s s p a t h " /> <c l a s s p a t h r e f i d=" j u n i t " /> </ j a v a c> </ t a r g e t> <t a r g e t name=" t e s t " depends=" c o m p i l e . " /> </ t a r g e t> <t a r g e t name=" j a v a d o c " . c l a s s " /> </ f i l e s e t> </ b a t c h t e s t> </ j u n i t> </ t a r g e t> <t a r g e t name=" t e s t . d i r } "> <i n c l u d e name=" T E S T . c o m p i l e . x m l .* . d i r } " /> <mkdir d i r=" $ { r e p o r t s . t x t . r e p o r t s " depends=" t e s t " d e s c r i p t i o n=" G e n e r a l o s i n f o r m e s d e l o s t e s t s e n f o r m a t o x m l "> < j u n i t r e p o r t t o d i r=" $ { r e p o r t s . x m l " depends=" c o m p i l e . d i r } " /> <j a v a c s r c d i r=" $ { s r c . c l a s s e s . h t m l . d i r } "> < f i l e s e t d i r=" $ { t e s t . c l a s s e s . d i r } " /> <j a v a c s r c d i r=" $ { t e s t . d i r } " d e s t d i r=" $ { b u i l d . d i r } " /> <mkdir d i r=" $ { r e p o r t s . c l a s s e s .t e s t s " d e s c r i p t i o n=" E j e c u t a l o s t e s t s u n i t a r i o s "> <mkdir d i r=" $ { r e p o r t s . A l l T e s t s " t o d i r=" $ { r e p o r t s . c l a s s p a t h " /> <c l a s s p a t h r e f i d=" j u n i t " /> <f o r m a t t e r t y p e=" p l a i n " /> < t e s t name=" t e s t . d i r } "> <c l a s s p a t h r e f i d=" t e s t .

n a m e } "> < f i l e s e t d i r=" $ { b u i l d . p r o j e c t . d i r } " /> < j a r d e s t f i l e =" $ { d i s t .257 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 depends=" c o m p i l e " d e s c r i p t i o n=" G e n e r a l a d o c u m e n t a c i o n d e l p r o y e c t o . d i r } / $ { d i s t . d i r } " d e s t d i r=" $ { r e p o r t s . n a m e } "> <c l a s s p a t h> <p a t h e l e m e n t path=" $ { t e s t .C l a s s " v a l u e=" c o n v e r s o r .1 " w i n d o w t i t l e=" $ { a n t . c l a s s e s . d i r } " /> <p a t h e l e m e n t path=" $ { b u i l d . "> 154 <j a v a 155 j a r=" $ { d i s t . d i r } / $ { d i s t . c l a s s e s . c l a s s e s . P r i n c i p a l " /> </ m a n i f e s t> </ j a r> </ t a r g e t> <t a r g e t name=" e x e c u t e " depends=" p a c k a g e " 153 d e s c r i p t i o n=" E j e c u t a l a a p l i c a c i o n . d i r } " /> </ c l a s s p a t h> </ j a v a d o c> </ t a r g e t> <t a r g e t name=" p a c k a g e " depends=" c o m p i l e " d e s c r i p t i o n=" G e n e r a e l f i c h e r o j a r " > <mkdir d i r=" $ { d i s t .1: Fichero Ant para la construcci´n del proyecto de conversi´n de o o temperaturas . j a v a d o c } " a u t h o r=" t r u e " version=" t r u e " u s e=" t r u e " a c c e s s=" p r i v a t e " l i n k s o u r c e=" t r u e " e n c o d i n g=" ISO .8 8 5 9 . n a m e } " 156 f o r k=" t r u e " /> 157 </ t a r g e t> 158 </ p r o j e c t> Listado A. "> <j a v a d o c s o u r c e p a t h=" $ { s r c . d i r } " /> <m a n i f e s t> <a t t r i b u t e name=" M a i n .

XML .258 ´ APENDICE A. BUILD.

} @Override public synchronized void s e t D a t o s ( double c a n t i d a d . } private void c a l c u l a C u o t a ( ) { double n = i n t e r e s / 1 2 0 0 . cantidad = cantidad . i n t e r e s = i n t e r e s . private double i n t e r e s . import g u i . h i p o t e c a . this . t h i s . tiempo = tiempo . modelo . double i n t e r e s ) . cuotaActualizada () . private double c a n t i d a d . public ModeloImpl ( ) { super ( ) . } Listado B. h i p o t e c a . double interes ) { this . V i s t a . public void s e t D a t o s ( double c a n t i d a d . i n t tiempo . import g u i . pow(1+n . private i n t tiempo . c u o t a = c a n t i d a d ∗n /(1 −(1/Math . } @Override public void s e t V i s t a ( V i s t a v i s t a ) { this .1: interface Modelo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package g u i . h i p o t e c a . calculaCuota () . v i s t a = v i s t a . i n t tiempo .Ap´ndice B e Aplicaci´n Hipoteca o C´digo fuente de la aplicaci´n del c´lculo de la cuota mensual de una hipoo o a teca 1 2 3 4 5 6 7 8 9 package g u i . V i s t a . vista . v i s t a . 259 . h i p o t e c a . modelo . 12∗ tiempo ) ) ) . public double g e t C u o t a ( ) . private double c u o t a . v i s t a . public c l a s s ModeloImpl implements Modelo { private V i s t a v i s t a . public i n t e r f a c e Modelo { public void s e t V i s t a ( V i s t a v i s t a ) .

A c t i o n E v e n t . h i p o t e c a . c o n t r o l a d o r . c o n t r o l a d o r . } Listado B. lang . h i p o t e c a . swing . .260 33 34 35 36 37 38 39 ´ ´ APENDICE B. A c t i o n L i s t e n e r . . s e t L a y o u t (new BorderLayout ( ) ) . C o n t r o l a d o r . . modelo . awt . C o n t a i n e r . . v i s t a . JLabel .2: Implementaci´n del interface Modelo o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package g u i . import g u i . import g u i . public void s e t M o d e l o ( Modelo modelo ) . JPanel . s w i n g . private J L a b e l j l C u o t a . public V i s t a I m p l ( ) { super ( ) . awt . C o n t r o l a d o r . APLICACION HIPOTECA } @Override public synchronized double g e t C u o t a ( ) { return c u o t a . h i p o t e c a . // Componentes g r ´ f i c o s a private C o n t a i n e r c o n t e n e d o r . } private void creaGUI ( ) { try { S w i n g U t i l i t i e s . public i n t e r f a c e V i s t a { public void s e t C o n t r o l a d o r ( C o n t r o l a d o r c o n t r o l a d o r ) . awt . v i s t a .3: interface Vista 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package g u i . S w i n g U t i l i t i e s . public double g e t I n t e r e s ( ) . import import import import import import import import import import java java java java java . JTextField . public void c u o t a A c t u a l i z a d a ( ) . h i p o t e c a . h i p o t e c a . awt . e v e n t . r e f l e c t . J P a n e l j p D a t o s = new J P a n e l ( ) . } } Listado B. e v e n t . import j a v a . import g u i . . awt . Modelo . InvocationTargetException . C o n t a i n e r . private J T e x t F i e l d j t f I n t e r e s . JButton . public C o n t a i n e r g e t C o n t e n e d o r ( ) . . creaGUI ( ) . swing . public i n t getTiempo ( ) . modelo . public double g e t C a n t i d a d ( ) . . private C o n t r o l a d o r c o n t r o l a d o r . . private J T e x t F i e l d j t f T i e m p o . . Modelo . h i p o t e c a . javax javax javax javax javax public c l a s s V i s t a I m p l implements V i s t a { private Modelo modelo . private J T e x t F i e l d j t f C a n t i d a d . c o n t e n e d o r . import g u i . BorderLayout . swing . invokeAndWait (new Runnable ( ) { @Override public void run ( ) { c o n t e n e d o r = new C o n t a i n e r ( ) . . swing .

j p D a t o s . j b C a l c u l a . printStackTrace () .NORTH) . j p D a t o s . controlador = controlador . setText ( cuota ) . jpCuota . } } v e n t a n a . g e t T e x t ( ) ) . } catch ( I n v o c a t i o n T a r g e t E x c e p t i o n e ) { e . printStackTrace () . } private c l a s s E s c u c h a d o r implements A c t i o n L i s t e n e r { @Override public void a c t i o n P e r f o r m e d ( A c t i o n E v e n t e ) { controlador . c o n t e n e d o r . } @Override public i n t getTiempo ( ) { return I n t e g e r . add ( jpCuota ) . } }) . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . . j p D a t o s . add ( j t f T i e m p o ) . } @Override public void c u o t a A c t u a l i z a d a ( ) { S t r i n g c u o t a = S t r i n g . j l C u o t a = new J L a b e l ( " C u o t a m e n s u a l : " ) . g e t C u o t a ( ) ) . BorderLayout . add ( j pD a t o s . p a r s e I n t ( j t f T i e m p o . add ( j t f C a n t i d a d ) . add (new J L a b e l ( " I n t e r e s : " ) ) . g e t T e x t ( ) ) . add ( j l C u o t a ) . } } @Override public double g e t C a n t i d a d ( ) { return Double . modelo = modelo . solicitadoCalculo () .261 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 j p D a t o s . n j t f T i e m p o = new J T e x t F i e l d ( 3 ) . v e n t a n a . c o n t e n e d o r . s e t V i s i b l e ( t r u e ) . add ( j b C a l c u l a ) . j p D a t o s . } @Override public void s e t C o n t r o l a d o r ( C o n t r o l a d o r c o n t r o l a d o r ) { this .2 f " . j p D a t o s . } // // // } @Override public C o n t a i n e r g e t C o n t e n e d o r ( ) { return c o n t e n e d o r . p a r s e D o u b l e ( j t f C a n t i d a d . p a r s e D o u b l e ( j t f I n t e r e s . EXIT ON CLOSE) . g e t T e x t ( ) ) . j t f I n t e r e s = new J T e x t F i e l d ( 5 ) . JButton j b C a l c u l a = new JButton ( " C a l c u l a " ) . } @Override public double g e t I n t e r e s ( ) { return Double . } @Override public void s e t M o d e l o ( Modelo modelo ) { t h i s . add (new J L a b e l ( " C a n t i d a d : " ) ) . pack ( ) . jlCuota . modelo . J P a n e l jpCuota = new J P a n e l ( ) . } catch ( I n t e r r u p t e d E x c e p t i o n e ) { e . a d d A c t i o n L i s t e n e r (new E s c u c h a d o r ( ) ) . j t f C a n t i d a d = new J T e x t F i e l d ( 8 ) . f o r m a t ( " C u o t a m e n s u a l : %. ventana . j p D a t o s . add ( j t f I n t e r e s ) . add (new J L a b e l ( " A ~ o s : " ) ) .

.4: Implementaci´n del interface Vista o 1 2 3 4 5 6 7 8 9 10 package g u i . public void s e t V i s t a ( V i s t a v i s t a ) . ControladorImpl . h i p o t e c a . c o n t r o l a d o r . } @Override public void s e t V i s t a ( V i s t a v i s t a ) { this . . import g u i . s e t D a t o s ( c a n t i d a d . } @Override public void s e t M o d e l o ( Modelo modelo ) { t h i s .262 ´ ´ APENDICE B. private V i s t a v i s t a . c o n t r o l a d o r . . ModeloImpl . import j a v a x . s w i n g . public i n t e r f a c e C o n t r o l a d o r { public void s e t M o d e l o ( Modelo modelo ) . import g u i . VistaImpl . v i s t a . modelo . v i s t a . h i p o t e c a . } private void e j e c u t a ( ) { . Controlador . . . h i p o t e c a .5: interface Controlador 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package g u i . modelo . double i n t e r e s = v i s t a . .6: Implementaci´n del interface Controlador o 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package g u i . public f i n a l c l a s s H i p o t e c a 2 { private H i p o t e c a 2 ( ) { super ( ) . modelo . } Listado B. public void s o l i c i t a d o C a l c u l o ( ) . Modelo . getTiempo ( ) . import g u i . tiempo . controlador . modelo . Modelo . Vista . public C o n t r o l a d o r I m p l ( ) { super ( ) . h i p o t e c a . . V i s t a . . import import import import import import gui gui gui gui gui gui . v i s t a . h i p o t e c a . } public void s o l i c i t a d o C a l c u l o ( ) { double c a n t i d a d = v i s t a . . JFrame . h i p o t e c a . V i s t a . v i s t a . modelo . Modelo . APLICACION HIPOTECA Listado B. v i s t a = v i s t a . modelo = modelo . controlador . i n t e r e s ) . import g u i . hipoteca hipoteca hipoteca hipoteca hipoteca hipoteca . public c l a s s C o n t r o l a d o r I m p l implements C o n t r o l a d o r { private Modelo modelo . . h i p o t e c a . i n t tiempo = v i s t a . g e t C a n t i d a d ( ) . } } Listado B. g e t I n t e r e s ( ) .

getContenedor ( ) ) .7: Programa principal . e j e c u t a ( ) . c o n t r o l a d o r . vista . Modelo modelo = new ModeloImpl ( ) . v e n t a n a . } public s t a t i c void main ( S t r i n g [ ] new H i p o t e c a 2 ( ) . s e t M o d e l o ( modelo ) . v e n t a n a . s e t V i s t a ( v i s t a ) . v i s t a . setVista ( vista ) .263 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 V i s t a v i s t a = new V i s t a I m p l ( ) . C o n t r o l a d o r c o n t r o l a d o r = new C o n t r o l a d o r I m p l ( ) . ventana . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . } } args ) { Listado B. setContentPane ( v i s t a . EXIT ON CLOSE) . s e t V i s i b l e ( true ) . modelo . pack ( ) . JFrame v e n t a n a = new JFrame ( " C ´ l c u l o d e l a c u o t a m e n s u a l d e u n a a hipoteca " ) . controlador . setControlador ( controlador ) . v e n t a n a . s e t M o d e l o ( modelo ) .

APLICACION HIPOTECA .264 ´ ´ APENDICE B.

u t i l . que debe ser el mismo. f i n a l i n t tConsumidor ) { Thread p r o d u c t o r = new Thread (new Runnable ( ) { @Override public void run ( ) { try { while ( true ) { contenedor . s t a r t () . Thread c o n s u m i d o r = new Thread (new Runnable ( ) { @Override public void run ( ) { try { while ( true ) { contenedor . nextInt (100) ) . s l e e p ( tConsumidor ) . 265 . import j a v a . getDato ( ) . } } }) . } private void e j e c u t a ( f i n a l i n t t P r o d u c t o . printStackTrace () . s l e e p ( t P r o d u c t o ) .1 muestra un ejemplo de uso de los Buffer definidos en o el Cap´ ıtulo 14. Thread . setDato ( a l e a t o r i o . printStackTrace () . private P r i n c i p a l ( ) { super ( ) . public f i n a l c l a s s P r i n c i p a l { // Deja una de l o s B u f f e r d e s c o m e n t a d o s p a r a v e r l a e j e c u c i o n ´ private B u f f e r S i n L o c k <I n t e g e r > c o n t e n e d o r = new B u f f e r S i n L o c k <I n t e g e r >(10) . Thread . } } }) . // p r i v a t e BufferConLock<I n t e g e r > c o n t e n e d o r = new BufferConLock<I n t e g e r >(10) . productor . } } catch ( I n t e r r u p t e d E x c e p t i o n e ) { e . } } catch ( I n t e r r u p t e d E x c e p t i o n e ) { e . Descomenta alguna de las l´ ıneas 7 u 8 para ver el resultado.Ap´ndice C e Ejemplo sincronizaci´n o El c´digo del Listado C. Random . private Random a l e a t o r i o = new Random ( 0 ) . 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 package b u f f e r .

p a r s e I n t ( a r g s [ 0 ] ) .266 45 46 47 48 49 50 51 ´ ´ APENDICE C. s t a r t ( ) . p a r s e I n t ( args [ 1 ] ) ) . I n t e g e r . } } Listado C. EJEMPLO SINCRONIZACION consumidor . } public s t a t i c void main ( S t r i n g [ ] a r g s ) { new P r i n c i p a l ( ) . e j e c u t a ( I n t e g e r .1: C´digo de ejemplo que usa los Buffer del cap´ o ıtulo 14 .

152] [6] Fran Reyes Perdomo y Gregorio Mena Carlos Bl´ Jurado. O’Reilly & Associates. [49. [103] e n ´ [7] Ben Collins-Sussman. 2006. Head first design patterns. 2007. 104. 2006. Addison Wesley Professional. O’Reilly Media. 2005. Clean code. 253] [10] Robert C. 1 edition. O’Reilly. 220] [2] Ken Arnold.Bibliograf´ ıa [1] Brian Goetz Tim Peierls Joshua Bloch Joseph Bowbeer David Holmes Doug Lea. Perarson. 2010. [73. [49. [219. James Gosling. 152. 2004. Michael Pilato. [171. 115. Almudena Sierra Alonso. Java Concurrency in Practice. Brian W. Effective Java. 2008. Java Network Programming. and David Holmes. El lenguaje de programaci´n Java. Fitzpatrick. [232. Version Control with Subversion. 203. [86] [8] John Erich Gamma Richard Helm Ralph Johnson Vlissides. Patrones de dise˜o. 2001. Pearson Educaci´n. [103. O’Reilly & Associates. Java Power Tools. [13] John Ferguson Smart. [49. 92.Addison Wesley. and C. De Euclides a Java. Juan Gue ti´rrez Plaza. Nivola. 2005. Historia de los algoritmos y de n los lenguajes de programaci´n. 2 edition. Pruebas de software y JUnit. 2009. 232. and Miren Idoia n Alarc´n Rodr´ o ıguez. 73. 253] n [9] Eric Freeman and Elisabeth Freeman. Pearson . 115. Lulu. Addison Wesley. 104] [11] Ricardo Pe˜a Mari. 2001. Martin. [22] o [12] Eliotte Rusty Harold. Prentice Hall. 171] [4] Joshua Bloch. 2003. Head First Java. 204] 267 . O’Reilly & Associates. 2008. 73. 220] o o [3] Bert Bates and Kathy Sierra. 220] [5] Daniel Bola˜os Alonso. 131. Dise˜o Agil con TDD. [229] [86.

78 lanzar una. 88 Colecciones. 78 Extensi´n de una clase. 125 Comodines. 32 o Flujos.clase. 33 o Constructor por defecto. 47 Control de Versiones. 127 Calendar. 55 Escuchadores. 130 Definici´n de un objetivo.clase. 197 Sincronizaci´n. 119 e Clases recubridoras.clase. 40 o File. 197 o 268 . 130 Java Collection Framework. 89 enum. 61 Detecci´n de eventos. 131 Generaci´n de la documentaci´n. 92 a ficheros. 55 Enumeraciones. 93 Gen´ricos e Borrado de tipo. 74 finally. 40 Hilos. 96 de bytes. 58 Clases gen´ricas. 115 Math.clase.clase. 76 inidcar que se lanza una. 135 o Estructurs path-like. 109 Comentarios de documentaci´n.´ Indice alfab´tico e Ant Ejecuci´ y limpieza. 129 o Definici´n de un proyecto. 172 Clases abstractas. 115 Date. 40 Herencia simple. 116 Scanner. 44 o Applet. 123 Genericos Ampliaci´n del tipo.clase. 122 o Gestores de aspecto. 158 Etiquetas HTML. 215 Anotaci´n Override. 115 Random. 132 o Empaquetado de la aplicaci´n. 135 o Ant Compilar un proyecto. 103 StringBuffer. 107 StringBuilder. 93 de caracteres. 139 Herencia. 74 try. 190 Cerrojos. 109 AWT(Abstract Window Toolkit). 159 Autoboxing. 107 abstract.clase. 96 Finalizaci´n. 141 o EclEmma. v´ase Detecci´n de evene o tos Excepciones catch.clase. 108 Cobertura de las pruebas. o o 134 Propiedades. 114 GregorianCalendar. 128 o Definici´n de una tarea. 157 Ciclo de vida. 138 Bugzilla. 74 delegar una.clase. 123 L´ ımite superior. v´ase Coe lecciones Ant. 50 Acoplamiento. 129 o Ejecuci´n de Pruebas Unitarias. 50 Clases e interface anidados.

v´ase Hilos e MyLyn. 62 Bater´ de prueba. 139 M´todos get y set. 214 n Programaci´n Orientada a Objetos. 150 JRadioButton. 138 Parameters. 229 Strategy. v´ase Gestores de e JTextField. 84 super. 86 JButton. 40. 79 Principios FIRST. 80 Recolector de basura. 146 RunWith.´ ´ INDICE ALFABETICO Subverion commit. 80 Threads. 139 Contenedores. 150 Test. 117 e 269 URL. 152 Patrones Abstract Factory. 85 Repositorio. 66 Subversion import. 209 Streams. 84 merge. 86 ıas svnserve. 42 Socket. 226 Patrones de dise˜o. 81 Integraci´n con Eclipse. 20 e Sistema de ficheros. 148 Layout Managers. 96 Sobrescritura de atributos. 207 TCP. 67 AfterClass. 31 Serializaci´n. 73 Mock Objects. 58 interface. 146 Test Suites. 46 BeforeClass. 64 JUnit. 87 JList. 46 o a Patr´n de dise˜o o n Singleton. 82 JLabel. 42 o Tipos gen´ricos. 62 Before. 147 aspecto Componentes. 53 import static. 56 Vinculaci´n din´mica. 11 o Pruebas unitarias. 207 UDP. 215 Modelo/Vista/Controlador. 70 o After. 21 implements. 98 o Signatura de un m´todo. 29 e M´todos gen´ricos. 165 Tipos de datos. 231 Factory Method. 217 Observer. 204 package. 118 e e Test unitarios. 86 JCheckBox. 53 Ocultaci´n de atributos. 58. 219 Decorator. v´ase Flujos e . 79. 85 Swing. 56 Paquetes.