Programación en Java

Curso de V erano de Málaga. Programación en Java.
Profesores: Sergio Gálvez Rojas José Luis Caro Herrero

Índice
Capítulo 0: Introducción.
Características generales Convenciones sobre cómo escribir programas. Comentarios y anotaciones.

Capítulo 1: Conceptos de Orientación a Objetos en Java.
Idea de la Orientación a Objetos en Java. Manejadores y objetos. Productores y consumidores. Visibilidad. Reutilización de código. Composición. Reutilización de código. Herencia. Herencia: es-un vs. es-como-un. Polimorfismo. Polimorfismo y vinculación dinámica. Recolector de basura. Colecciones e iteradores. Downcasting vs generics. Manejo de excepciones. Multitarea. Persistencia. Java y los applets. Java y las aplicaciones standalone.

Capítulo 2: Objetos en Java.

S G R

¿Dónde se almacenan los datos en un programa? Tipos básicos o primitivos. JDK 5 y autoboxing Tipos especiales. Arrays. Recolector de basura. Creación de nuevos tipos: class. Métodos, parámetros y valores de retorno. Utilización de componentes. Cosas static. Importación estática. El primer programa. Operadores Java. Ejemplos de uso de operadores. Comparación e igualdad de objetos. Casting y literales.

Sentencias de control de flujo.

Capítulo 3: Inicialización de objetos.
Constructores. Constructores con parámetros. Sobrecarga de funciones. Sobrecarga del constructor. La palabra clave this. Llamada a un constructor desde otro constructor. Uso de this en un constructor. Inicialización de datos estáticos. Sobrecarga del constructor. Inicialización de arrays. Número variable de argumentos.

Capítulo 4: Reutilización de código.
Package. Los ficheros .jar. Paquetes y colisiones. Visibilidad. Composición. Herencia. Visibilidad. Inicialización en herencia. Composición y herencia. Upcasting. La palabra clave final. Polimorfismo. La palabra clave abstract. Interfaces. Clases internas. Polimorfismo y constructores. Downcasting. Downcasting y RTTI.

Capítulo 5: Colecciones.
Vectores. Java no tiene clases parametrizadas. Enumerators. Hashtables. Enumerators. Colecciones y Java 1.2. Test de List.

Capítulo 5,5: Clases genéricas y enumerados.
Clases genéricas. Crear genéricos simples. Genéricos y subtipos. Supertipo base. Recorrido de colecciones. Comodines acotados. Métodos genéricos. Más sobre comodines.

Colecciones tradicionales. Un .class para todas las clases instanciadas. Erasure y herencia múltiple. Enumerados. Constructor de enumerados. Comportamiento diferenciado entre constantes. Clases de apoyo.

Capítulo 6: Tratamiento de excepciones.
Elevar y atrapar una excepción. Captura y relanzamiento. Palabra reservada finally. Ejemplo. Detalles sobre excepciones.

Capítulo 7: E/S con Java.
Estratificación. Ejemplo: Fichero de entrada con buffer. Ejemplo: Entrada desde una cadena. Ejemplo: Cadena de entrada con buffer. Ejemplo: La entrada estándar. Salida de datos. Ejemplo: Escritura en un fichero de texto. Ejemplo: Guardar y recuperar datos. Ficheros de acceso directo. La clase File. Stream Tokenizer. E/S con Java 1.1. Entrada. E/S con Java 1.1. Salida. Compresión. Ficheros .jar. Persistencia. Ejemplo de serialización. La interfaz Externalizable. Ejemplo de Externalizable. Más sobre serialización. Ejemplo.

S G R

Capítulo 8: Metaclases.
Ejemplo. Metaclases en JDK 5.

Capítulo 9: Copias.
Copias locales. Ejemplo.

Capítulo 10: Concurrencia.
Concurrencia. La palabra clave synchronized. Estados de un thread. Ejemplo final.

Capítulo 11: Programación Windows con Java.
Applets y aplicaciones independientes. El primer applet.

La etiqueta applet. Fuentes y colores. Ciclo de vida de un applet. Paso de parámetros en un applet. Recuperación de parámetros desde un applet. Comunicación con el navegador. Ventanas. Primer ejemplo de una ventana. Distribución de componentes: Layout. FlowLayout. BorderLayout. GridLayout. CardLayout. Manejo de eventos. Ejemplo con action(). Ejemplo con handleEvent(). Componentes. TextField. TextArea. Label. Checkbox. CheckboxGroup. Choice. List. MenuComponent. MenuIetm, setActionCommand(), MenuShortCut. Canvas. Eventos de teclado, ratón y foco. Ejemplo: foco, teclado, ratón. Canvas. Dialog. FileDialog. Java 1.1. Eventos en Java 1.1. Eventos soportados. Ejemplo de un botón. Ejemplo de un botón con clases internas. Aplicaciones y applets todo en uno. Java Swing. Bordes. Botones. Iconos. Visualización de ejemplos JDBC Ejemplo de JDBC Comunicación vía sockets Servidor Cliente Servir a muchos clientes Acceso por Internet a bases de datos: applets y threads Internet, BB.DD. y applets

El servidor (cont.DD. Servidor Servlets HTML y formularios Ciclo de vida de un servlet Clases para servlets Ejemplo de servlet Capítulo 12: RMI RMI. El applet Internet y BB. Métodos Manejo de excepciones Capítulo 14: Internacionalización Internacionalización I18n: Ejemplo básico Aspectos a internacionalizar Texto y datos intercalados Ejemplo con MessageFormat Formato de fechas y horas Fechas y horas.) RMI. El cliente Parámetros Retrollamadas Descarga de clases Política de seguridad Activación remota de objetos Protocolo de activación Ejemplo de activación Capítulo 13: Ejecución de programas no Java. Campos Acceso al objeto principal. JNI Ejecución de programas no Java JNI.DD. Ejemplo Patrones para fechas y horas Ejemplo de formato Formato de números Patrones para números Ordenación Reglas de ordenación S G R Capítulo 15: Introducción a JSP Funcionamiento Instalación Componentes JSP . Compilación del programa C Paso de parámetros jstring Arrays nativos Acceso al objeto principal. El servidor La comunicación RMI.Creación de tablas en HTML Internet y BB.

Depuración Manipulación del cuerpo Ejemplo de bucle Ámbito de objetos Etiquetas anidadas Bases de datos Etiquetas Java Descriptor de etiquetas .Primer ejemplo Expresiones JSP Scriptlets Scriptlets y condiciones Declaraciones Directiva page. Atributos Ejemplo con page Ejemplo de upload Capítulo 16: Etiquetas jsp: y JavaBeans Ejemplo de jsp:page La etiqueta jsp:plugin Uso de JavaBeans Sintaxis Ejemplo de JSP y JavaBeans Asignación de parámetros Ejemplo Capítulo 17: Biblioteca de etiquetas (Tags) Primer ejemplo La clase Tag Tag Library Descriptor Segundo ejemplo Etiquetas con cuerpo Tercer ejemplo.

Programación en Java.2005 -1- Capítulo 0 Introducción p Java es un lenguaje pseudointerpretado: . no es necesario poner la extensión.class. S G R Capítulo 0: Introducción.java se compila con: javac file.class contiene un código intermedio (formado por bytecodes) que debe ser interpretado por el ejecutor java. que se ejecuta con: java file * El fichero file.java y genera un fichero file.class.Un fichero file. * Para ejecutar un fichero . Cursos de Verano de Málaga . .

dejan el código máquina traducido en un buffer para no tener que volver a traducirlo.2005 -2- Características generales * Originalmente. * Java es seguro. .Compiladores que generan código nativo (código máquina) en lugar de pseudocódigo. Java era muy lento.Programación en Java. Con esto se pierde portabilidad. Capítulo 0: Introducción. ya que es pseudointerpretado. Impide accesos indebidos. * Para evitar aproximaciones: la lentitud hay dos . y controla más condiciones de error que otros lenguajes. . como C++. con lo que una nueva ejecución de ese trozo de código será más rápida al no requerir una nueva traducción. * ¿Para qué generar código intermedio y no código máquina puro? Para conseguir que los programas sean portables y que se puedan ejecutar en cualquier máquina con independencia del :p que posea. pero actualmente emplea optimizaciones que sólo lo hacen 2 veces más lento que C++.Ejecutores JIT (Just In Time). Éstos. Cursos de Verano de Málaga . a medida que van traduciendo el pseudocódigo a código máquina y lo van ejecutando.

2005 -3- Características generales * Java permite tener las distintas partes que componen un programa distribuídas por la red. R .2. 1. * Por desgracia.4 (conocidas como JDK 2) y 1. tanto si la máquina es multiprocesador como si no.0.1 (las más antiguas). * Java es un lenguaje multitarea. S * En Java no es tan importante el lenguaje como G las librerías que ya incorpora. 1. * Java permite trabajar con Bases de Datos vía JDBC (Java DataBase Connectivity).Programación en Java. 1.5 (JDK 5). 1. Capítulo 0: Introducción. Actualmente hay varias versiones fundamentales del JDK (Java Development Kit) que son: 1. Java evoluciona a un ritmo vertiginoso.3. Cursos de Verano de Málaga . * No podemos remitirnos exclusivamente a la última versión porque no todos los clientes potenciales de nuestras aplicaciones tienen porqué poseer la versión más moderna.

. Cursos de Verano de Málaga . debe contener obligatoriamente un tipo de objetos (clase) llamado Xxx. Aparece en escena el concepto de manejador. Un manejador viene a ser como un puntero a objetos en C++. y si un fichero se llama Xxx.2005 -4- Características generales * En Java todo son objetos. .java.java. que no se consideran objetos y se tratan de forma especial. * Java no posee punteros. char. * Existe una excepción: los tipos primitivos.Programación en Java. etc. tales como int. * Los ficheros fuente tienen la extensión . Capítulo 0: Introducción. con la diferencia de que en Java todos los objetos deben ser controlados obligatoriamente a través de un manejador. Incluso el programa principal se enmarca dentro de un objeto.

Programación en Java. Ej.2005 -5- Convenciones sobre cómo escribir programas * No es aconsejable usar el carácter de subrayado en los identificadores de usuario.023e+23. excepto la primera palabra que comenzará por minúscula. Si se emplean varias palabras.: NUMERO_DE_AVOGADRO = 6. ClaseDeEjemplo S G que conforman un paquete * Los nombres de los subdirectorios van completamente en minúsculas.: identificadorDeEjemploParaEsteCursoDeVerano * Los nombres de las clases deben comenzar por mayúscula.* R * Los nombres de las constantes (final static) se colocan con todas las letras en mayúsculas. Cursos de Verano de Málaga . Capítulo 0: Introducción. y con la inicial de cada palabra en mayúscula. cuando esté formado por varias palabras. . Ej.: mipaquete. se separan por subrayados.otrodirectorio. Ej. se escribira con todas las palabras juntas. * Cualquier identificador de usuario.

y la coloca en un fichero HTML. . * Existe una herramienta llamada javadoc que extrae documentación automáticamente de nuestros programas. Cursos de Verano de Málaga . y pueden ser: Para todos (el único admitido por los campos): @see NombreDeClase Permite referenciar a la documentación de otras clases. un campo o un método.2005 -6- Comentarios * En Java los comentarios son como en C. Sólo para las clases: @version información de la versión @author información del autor Sólo para los métodos: @param nombreDeParametro descripción @return descripcion @exception NombreDeClaseCompletamenteCalificado descrip.Programación en Java. Capítulo 0: Introducción. @deprecated Los métodos marcados con deprecated hacen que el compilador emita una advertencia (warning) si se utilizan. * Para ello se utiliza un comentario que empieza por /** y acaba con */ * Estos comentarios deben colocarse siempre justo antes de una clase.

O. darle una solución que pueda ser interpretada en la vida real. se pretende simular el problema real mediante medios computacionales para.Programación en Java. etc. p Espacio de las soluciones: Es el ámbito en el que vamos a solucionar el problema. También llamado espacio computacional. S G R p De alguna manera. de Java p Espacio del problema: Es el ámbito en el que se enmarca el problema que queremos solucionar: emitir unas nóminas por impresora. el ordenador. Capítulo 1: Conceptos O. gestionar los pedidos de clientes.O. . de Java. Cursos de Verano de Málaga . o sea. mediante el ordenador. poner un satélite en órbita.2005 -1- Capítulo 1 Conceptos O.

Cursos de Verano de Málaga . p Conclusión: Un objeto tiene un estado que puede modificar como consecuencia de su respuesta a un mensaje. Capítulo 1: Conceptos O. son susceptibles de recibir los mismos mensajes.Un programa es un cúmulo de objetos que se dicen entre sí lo que tienen que hacer a través de mensajes.Cada objeto tiene una memoria interna (estado). Según la terminología O.O.Todos los objetos de un tipo concreto... . p Esto se fundamenta en cinco puntos básicos: 1.. formada por otros objetos más pequeños.Programación en Java. 4. así hasta llegar a objetos básicos o primitivos.2005 -2- Idea de la O... creando nuevos tipos de objetos.Todo es un objeto. un tipo es lo mismo que una clase. en Java p La idea es: El programa se debe adaptar a la «jerga» del problema real.O. 5. 3.O. 2. de Java. de manera que al leer el código que implementa la solución. se esté leyendo algo que expresa el problema en sí.Todo objeto pertenece a un tipo.

p Las peticiones que se pueden hacer a un tipo quedan determinadas por su interfaz. Capítulo 1: Conceptos O. p Asociado a cada mensaje de la interfaz. .O. Sin embargo.encender(). y éstos los redirigen al objeto concreto al que apuntan. y asociar el objeto con el manejador. Todos los objetos se crean obligatoriamente con new. de Java. hay un método. sino a través de manejadores. que es un trozo de código que se ejecuta cuando el objeto recibe el mensaje correspondiente. p Los mensajes se le envían a los manejadores. simplemente declarando b. Cursos de Verano de Málaga .Programación en Java. con new. b. p En Java no se manejan los objetos directamente. una clase es lo mismo que un tipo. Es necesario crear R un objeto Bombilla. Bombilla b = new Bombilla(). S p Es necesario crear un manejador G de Bombilla. todavía no existe ningún objeto bombilla.2005 -3- Manejadores y objetos p En O.O.

para hacerla más eficiente. y consumidores de clases.. p También se pueden ocultar algunos de los mensajes que puede recibir el objeto. modificar dicha clase (manteniendo su interfaz).2005 -4- Productores y consumidores p En programación O. al igual que hay productores de chips y consumidores de chips para crear placas más grandes. con lo que el productor la podrá cambiar a su antojo. Capítulo 1: Conceptos O. Esto es una ventaja también para el cliente. y una vez concluido todo. p ¿Por qué ocultar la implementación? 1) Así el cliente no tendrá acceso a ella. 2) Es posible crear una clase de objetos de una forma fácil e ineficiente (para agilizar el desarrollo). así como algunos de los componentes de su estado.Programación en Java. el sistema se parece más a la creación de hardware. Cursos de Verano de Málaga .O. sin preocuparse de dañar el funcionamiento del código de los clientes. .O. que sabe lo que puede utilizar sin ningún posible perjuicio posterior. de Java. Hay productores de clases.

métodos y variables métodos y variables clases.Programación en Java. Capítulo 1: Conceptos O. métodos y variables private private protected* * protected S G U R U U U U U U U U U U métodos y variables métodos y variables U Sólo en la versión 1. . interfaces. interfaces. Modificador Se aplica a Ella Package Hijas Otras misma clases public clases.0 de Java. de Java.O. Cursos de Verano de Málaga .2005 -5- Visibilidad p Palabras reservadas para ocultar cosas internas a un objeto: Se anteponen a cada uno de los elementos internos de que consta un objeto.

Programación en Java. P. X Reenviar el mensaje a objetos que él mismo contiene. Cursos de Verano de Málaga . X Reenviar el mensaje a otros objetos externos. Composición p La forma más directa de usar una clase de objetos es creando objetos concretos.O. Cuando un objeto recibe un mensaje..ej. dentro del método asociado a éste puede: X Responder directamente.2005 -6- Reutilización de código. . de Java. la clase de objetos Coche posee cuatro objetos de la clase Rueda. p Así. p Relación Tiene-un: También se puede decidir que un elemento concreto compone a otro tipo de objetos más general. y así sucesivamente. Capítulo 1: Conceptos O. un objeto puede contener a muchos otros.

Cursos de Verano de Málaga . Esto es lo que se denomina herencia. se crea una nueva que contiene todos los elementos G de la padre.O. modificar la estructura de la copia. pero me quiero comportar de forma distinta». Java implementa la herencia con la palabra reservada extends. Herencia p Relación es-un: En O.2005 -7- Reutilización de código. derivada o hija). una copia de su interfaz. Se permite coger una clase. crear un copia idéntica de la misma (clon). XModificar el funcionamiento de las funciones ya existentes en la clase padre. R p Para diferenciar la clase hija de la padre se puede: XIncluir nuevas funciones a la clase hija. . se modifica posteriormente. no sólo los componentes del estado. aunque Java hace que si la clase original (llamada clase base o padre). Capítulo 1: Conceptos O. S p Cuando se hereda de una clase. Es lo que se llama reescritura. sino. la clase copia (también llamada clase heredera. más importante aún.Programación en Java. y crear así una nueva clase.O. de Java. p La reescritura viene a decir algo así como: «Estoy empleando la misma interfaz que mi padre. también reflejará esos cambios.

Programación en Java. Es lo que se llama sustitución pura. pero (debido a su definición) sólo podrá dirigir los mensajes que el padre tiene definidos. que además de frío puede dar calefacción. Ej. también puede apuntar a objetos hijos. . un manejador a objetos padre. Se nos rompe el sistema de aire acondicionado. No se cambia el panel de control.: Sea un sistema de aire acondicionado. De esta forma. Aunque el nuevo objeto (la bomba de calor) tiene una interfaz más completa. Se sustituye por una bomba de calor. Cursos de Verano de Málaga . de Java. quiere decir que un manejador puede apuntar tanto a objetos de la clase padre como a los de la clase hija. No se puede hacer al revés (control de bomba de calor y sólo sistema de aire acondicionado).O. nuestro manejador no nos permite la comunicación.2005 -8- Herencia: es-un vs es-como-un p Controversia respecto a la herencia: ¿Debe limitarse una clase hija a reescribir los métodos de su padre? En otras palabras ¿deben tener las clases hijas exactamente la misma interfaz que la padre? Si se obliga a esto. Capítulo 1: Conceptos O. ya que ambos tienen la misma interfaz. Sea el panel de control del aire acondicionado. El panel de control controla al sistema. Hay veces en las que interesa que la interfaz de la clase hija sea más rica que la del padre.

Segmento s = new Segmento.dibujar(). { Circulo c = new Circulo. puesto que un manejador de Figura también puede manejar objetos de clases hijas. Triangulo.R Si hacemos: void demo(Figura f) { f.2005 -9- Polimorfismo p La herencia se representa mediante un árbol invertido. Esto es lo que se llama upcasting. como mínimo tienen la misma interfaz. demo(c).. // . demo(q). de Java. demo(s).O. Cuadrado q = new Cuadrado. . ya que. Capítulo 1: Conceptos O.ej.Programación en Java. p La gran ventaja. f.. Cursos de Verano de Málaga . es que si ahora decidimos hacer otra clase hija.borrar(). p. S G Esta función nos remite a cualquier Figura independientemente de ninguna subclase concreta. como Circulo o Cuadrado. el trozo de código anterior sigue siendo útil. p Sea la siguiente función Java: todo funciona bien.

esto es. de Java.O. el de los Circulos cuando se llama con c. p Las interfaces son clases abstractas que sólo permiten declarar el prototipo de todos los métodos que deben implementar las clases que quieran ser hijas suyas. una especie de esqueleto. es algo que sólo puede hacerse dinámicamente. . Cursos de Verano de Málaga . pero no permiten crear objetos de su tipo. Se emplea la palabra reservada abstract. Para heredar de una interfaz no se usa la palabra extends sino la palabra implements. p Sólo en tiempo de ejecución se sabe cuál es el verdadero objeto a que se está apuntando. Por eso. vincular el método adecuado con el tipo de objeto correspondiente. el de los Cuadrados cuando se llama con q. Capítulo 1: Conceptos O.Programación en Java. Se utiliza la palabra reservada interface en lugar de class. a pesar de todo.2005 -10- Polimorfismo y Vinculación dinámica p Lo curioso del código anterior es que. el código que se ejecuta en demo() no es el correspondiente a Figura. y el de los Segmentos cuando se llama con s. p Las clases abstractas permiten crear un marco de trabajo. sino el correspondiente al objeto de verdad que se está gestionando.

No existen cosas como delete o free. X Como variables anónimas. En memoria estática.O. X Como variables locales. R p El recolector de basura actúa cuando la memoria disponible alcanza un límite demasiado pequeño. y el sistema ya se encargará de recogerlos cuando sea necesario. En el stack. p Con Java no hay que preocuparse de recolectar los objetos inaccesibles. Es lo que se llama G recolección de basura. de Java. Capítulo 1: Conceptos O. Cursos de Verano de Málaga . S p Java recupera automáticamente los objetos creados e inaccesibles a través de ningún manejador. . p En otros lenguajes.Programación en Java. es necesario liberar la memoria ocupada por los objetos almacenados en el heap.2005 -11- Recolector de basura p En otros lenguajes se crean objetos en distintaz zonas de memoria: X Como variables globales. p Los programas se limitan a crear todos los objetos que se necesiten. p A priori es impredecible saber cuando va a comenzar a funcionar el recolector de basura. aunque el usuario desconoce cuando se producirá dicha recolección. En el heap.

Si no se la maneja directamente. de Java. . p Entre las colecciones disponibles hay Listas. p La colección.Programación en Java. se tiene el concepto de iterador. y sin depender de las características concretas de cada una de ellas. al comienzo del diseño. etc. sin que cambie el código que accede a la colección. Capítulo 1: Conceptos O. Un array es un objeto que contiene una secuencia de objetos de un tamaño concreto.2005 -12- Colecciones e iteradores p Java dispone de arrays. sino a través de un iterador. queda reducida al concepto de secuencia mediante el empleo de iteradores. Vectores. se puede utilizar una lista. Cursos de Verano de Málaga . se puede decidir cambiar la Lista por un Vector.O. p De esta forma. Conjuntos. ¿Qué ocurre cuando no se conoce el número de elementos a insertar? p Java posee unas clases predefinidas llamadas collections en las que se permite insertar un número indeterminado de objetos. Para acceder a cualquiera de estas colecciones de manera uniforme. sea cual sea. Tablas hash.

es necesario hacerle explícitamente un downcasting. Cursos de Verano de Málaga .2005 -13- Downcasting vs generics p ¿Qué tipo de objetos se meten en una colección? Se meten objetos de la clase Object. S G R p Otros lenguajes permiten instanciar una clase creando una nueva clase en el que el tipo base se sustituye por uno concreto. p ¡Cuidado!: lo que sale de una colección es un Object. de Java. Luego por upcasting se puede meter cualquier objeto no primitivo. . Por ello. incluso los que creamos nosotros mismos. Java lo hace heredar automáticamente de Object.O. Java controla en tiempo de ejecución que el downcasting no es erróneo. y no un objeto del mismo tipo que el que nosotros metimos. Capítulo 1: Conceptos O. Pero ¡cuidado! cualquier otro objeto exista en nuestro programa.Programación en Java.

de Java.Programación en Java. T Si el control es concienzudo. T Esto se hace con: X Switches globales que tienen que testarse cada vez que se llama a una función. X Valores de retorno en las funciones que tienen que testarse. p Java utiliza el concepto de excepción.2005 -14- Manejo de excepciones p En otros lenguajes el propio usuario tiene que controlar el control de errores. . Una función puede acabar correctamente. Las excepciones se capturan en ciertos lugares bien definidos dentro del código Java. Cursos de Verano de Málaga . el resultado son programas de difícil legibilidad.O. o bien lanzando una excepción. Capítulo 1: Conceptos O.

2005 -15- Multitarea p Java emplea el concepto de multithreading. p Java permite la creación de tareas o subprogramas de ejecución independiente. Es lo que se llaman threads. p En lenguajes anteriores. p Si la máquina posee varios procesadores. Cursos de Verano de Málaga .O. Esto hace que el código sea muy dependiente de la máquina. para simular que se hacen varias cosas a la vez. . Capítulo 1: Conceptos O.Programación en Java. S G p Cualquier programa puede dividirse en las tareas que se quieran. p Se utiliza la palabra synchronized para indicar los trozos de código que no se pueden ejecutar simultáneamente por dos threads. los threads se repartirán entre ellos automáticamente. de Java. R p Las tareas deben implementar la interfaz Runnable. había que recurrir a las interrupciones.

p Hay dos tipos de persistencia: X Implícita: Todos los objetos de una clase determinada se almacenan en disco. de Java. . Capítulo 1: Conceptos O. p Para ello. X Explícita: El programador debe indicar en el programa cuándo guardar y recuperar de disco.2005 -16- Persistencia p La persistencia permite que los objetos sobrevivan incluso después de apagar la máquina. los objetos se almacenan en disco.Programación en Java. así como el tipo de objeto que se quiere guardar/recuperar.O. Cursos de Verano de Málaga . y en disco es necesario guardar referencias para mantener dichas conexiones. p Es difícil de implementar debido a que los objetos pueden contener otros objetos (composición).

la descarga del programa se hace por módulos y dinámicamente a medida que lo va requieriendo el usuario en la máquina cliente. Esta distribución se produce en el momento en que lo requiera el cliente.Programación en Java. O sea. como la imposibilidad de leer/escribir del disco del ordenador cliente. X Supone una forma de distribuir programas desde un almacén de programas al ordenador cliente. . sin que sean necesarias reinstalaciones ni nada por el estilo. X Para evitar programas malignos y «caballos de Troya» se imponen ciertas restricciones (quizás excesivas) a los applets. sino que se van tomando del servidor sólo aquellas partes del programa a las que el usuario quiere acceder. X El cliente obtiene la última versión del programa que haya almacenodo en el servidor de programas. Cursos de Verano de Málaga .2005 -17- Java y los applets p Un applet es un programa diseñado para ser ejecutado en un navegador como Netscape o IE. y no antes. activa el applet que comienza así su ejecución. Cuando el navegador carga la página. S G R p La ventaja de un applet Java sobre un script es que los programas Java están compilados. X El programa no se transfiere al completo. y el cliente no tiene forma de llegar al fuente. p Un applet forma parte de una página web. Capítulo 1: Conceptos O. de Java.O.

.Se hacen chequeos de límites de arrays.2005 -18- Java y aplicaciones standalone p Puede emplearse el lenguaje Java para hacer aplicaciones completas. de Java. como en cualquier otro lenguaje.O. y en que produce programas mucho más robustos. en el sentido de que: .Se hacen potentes chequeos de tipos. Capítulo 1: Conceptos O.No es necesario recoger la memoria con dispose o free. . sino que el propio sistema se encarga de ello a través del recolector de basura. .Programación en Java. Cursos de Verano de Málaga . estas restricciones no existen en las aplicaciones independientes o standalone. sino en la facilidad de programar.No se tiene un control directo de la memoria (no existe el concepto de puntero). . p Si bien los applets tienen ciertas restricciones en su ejecución (para evitar la proliferación de programas malignos). p La potencia de Java cuando se hacen aplicaciones independientes no está sólo en su portabilidad.

String s.ej..2005 -1- Capítulo 2 Objetos en Java p En Java los objetos se gestionan a través de manejadores. pero no ningún objeto de tipo String. sólo estamos declarando el manejador. Todos los objetos se crean R siempre con new. P. Capítulo 2: Objetos en Java. S G * Los manejadores sólo tienen sentido cuando se conectan a un objeto de verdad. y nunca directamente. . Cursos de Verano de Málaga . s = new String("abcd"). * En este caso también estamos dando información de cómo construir el objeto de tipo String al darle un parámetro en el momento de la creación.Programación en Java. si se hace: String s. y se conectan a los manejadores mediante el símbolo de asignación =.

pero no los objetos. y dicha recogida la hace el sistema automáticamente. p En el heap. Es un enorme bloque de memoria del que se van cogiendo trozos según se van necesitando. Este método se utiliza cuando se quiere que un objeto viva incluso después de que haya finalizado la ejecución del programa. El programador no tiene control sobre esto. Capítulo 2: Objetos en Java. Tiene la ventaja de que es muy fácil recoger los trozos de memoria que ya no se usan.2005 -2- ¿Dónde se almacenan los datos en un programa? p En los registros del procesador. p En el propio código. . Cursos de Verano de Málaga . Cuando se usan constantes. Esta es la pila de registros de activación. Java recoge los trozos que ya no son necesarios. p Fuera de memoria RAM. pero tomar y recoger trozos consume mucho tiempo. Se utiliza un trozo de memoria parecido al que se emplea para guardar el código ejecutable. Java nunca guarda nada aquí.Programación en Java. p En el stack. éstas se pueden almacenar como parte del propio código ejecutable. p En el almacenamiento estático. Aquí sólo se almacenan los manejadores de objetos.

En un tipo primitivo el tipo y el objeto son la misma cosa.2005 -3- Tipos básicos o primitivos p Hay una excepción a la regla «Todo son objetos en Java».0d 0 0 0 * El tamaño es siempre el mismo independientemente de la máquina. cada tipo primitivo tiene una clase asociada llamada wrapper. aunque siempre a través de manejadores. // I es un manejador. Los tipos primitivos son: Tipo primitivo boolean char byte short int long float double void Tamaño en bits 1 16 8 16 32 64 32 64 Valor por defecto false '\u0000' (byte)0 (short)0 Clase asociada Boolean Character Byte Short Integer Long Float Double Void BigInteger BigDecimal S 0L G 0. Integer I = new Integer(16). que puede almacenar el mismo tipo de información. La excepción la suponen los tipos primitivos. Cursos de Verano de Málaga .0f R 0. . * Para poder trabajar con los tipos primitivos como si fueran clases. int i = 16. // i es un tipo primitivo. Capítulo 2: Objetos en Java.Programación en Java.

Cursos de Verano de Málaga . x = i. * Sin embargo. . Por tanto cuidado con el operador ==. * La autoconversión es especialmente útil cuando una función espera un tipo wrapper. Así.5 permite el autoboxing o autoconversión. * La autoconversión es realizada por el compilador por lo que internamente un tipo primitivo sigue siendo diferente de su tipo wrapper. * El JDK 1. ya que se le puede pasar directamente un valor primitivo. int x = new Integer(8).5: Integer i = 7.2005 -4- JDK 5 y autoboxing p Los tipos BigInteger y BigDecimal permiten emplear valores enteros y decimales de cualquier precisión. La autoconversión permite asignar valores primitivos a un wrapper y viceversa. Capítulo 2: Objetos en Java. las siguientes sentencias son válidas a partir de JDK 1.Programación en Java. producirían un error en ejecución ya que los tipos primitivos no pueden albergar el valor null. las sentencias: int x. Integer i = null.

y que. Cursos de Verano de Málaga . . y si es un manejador se inicializa a null. s2[2] = new String[20]. S G R * En Java una matriz de dos o más dimensiones se trata como un manejador de secuencias de arrays de una dimensión. * Java garantiza que los elementos de un array se inicializan a cero. s1[2] = new String("Tres"). los subarrays del mismo nivel no tienen porqué tener las mismas dimensiones. s1 = new String[4]. * Dado que un array es un manejador. lo que se tiene realmente es un array de manejadores. * En Java. s1[0] = new String("Uno"). s2 = new String[3][]. es necesario asociarle un objeto con new.s1[3] = new String("Cuatro"). de la forma: String s1[]. s2[0] = new String[10]. si se intenta sobrepasar los límites. String s2[][]. Si es un tipo primitivo se inicializa a 0. Las variables locales a una función no son inicializadas.s1[1] = new String("Dos"). Capítulo 2: Objetos en Java.Programación en Java. s2[1] = new String[15]. en tiempo de ejecución. Arrays p Cualquier variable que conforme el estado de un objeto es automáticamente inicializada por Java. * Cuando se crea un array de objetos. se producirá un error. Además. * También se pueden crear arrays de tipos primitivos. un array se considera un manejador de secuencias.2005 -5- Tipos especiales.

Capítulo 2: Objetos en Java. * Automáticamente se activa el recolector de basura cuando la memoria se está agotando. Cursos de Verano de Málaga .2005 -6- Recolector de basura p Java se encarga de recoger todos los objetos que ya no estén siendo usados por nuestro programa. * La incertidumbre sobre la recolección de basura hace que no se pueda emplear Java en sistemas en tiempo real. en las que el usuario tiene cierto control sobre los tiempos de ejecución del recolector de basura. * La recolección de basura puede consumir bastante tiempo. * Hay implementaciones del motor de ejecución de Java. .Programación en Java.

Componen el estado.2005 -7- Creación de tipos nuevos: class p Para crear un tipo nuevo se usa la palabra class seguida del nombre del tipo. así como crear objetos SoloDatos. char c. } * Esta clase viene a ser como un registro de C. class MiClase { /* Cuerpo de la clase */ } Y los objetos se crean como: MiClase m = new MiClase(). Si son objetos deben ser inicializados en una función especial llamada constructor. * En el cuerpo de una clase se colocan: .Programación en Java. pero podemos crear manejadores a objetos SoloDatos. class SoloDatos { int i. float f. SoloDatos sd = new SoloDatos(). Pueden ser objetos (manejadores) o tipos primitivos.i = 16. .c = 'g'. sd. * Ej. sd.f =1. S G R Capítulo 2: Objetos en Java.2365f.Datos miembro (campos). Cursos de Verano de Málaga . Esta clase no hace nada. * Los datos miembro se acceden como los campos de los registros en C: sd.Funciones miembro (métodos). * Cada objeto mantiene su propia copia de los datos miembros. .

* Un método puede retornar cualquier tipo de objeto. p Los métodos de una clase no son más que funciones en el sentido de C. Los valores se retornan con return. return (short)3. * Los métodos determinan los mensajes que un objeto puede recibir. Podemos decir que siempre hay un objeto implícito que es el que recibe mensaje. lo que realmente se están pasando son manejadores.2005 -8- Métodos. * Ej. short miMetodo(char c.3f). float f) { // Cuerpo del método. * Como cualquier función. Cursos de Verano de Málaga . cuando se pasan objetos como parámetros. incluido un tipo primitivo. short s = mc. Capítulo 2: Objetos en Java. parámetros y valores de retorno. } } MiClase mc = new MiClase().: class MiClase { int a. se le asocia el objeto sobre el que se quiere ejecutar.miMetodo('h'.a = 23.Programación en Java. * Cuando se quiere ejecutar un método. . se indica el tipo void. * El cuerpo de un método se fundamenta en que cuando se ejecute lo hará sobre un objeto concreto. 3. Si no se quiere retornar nada. mc. un método puede recibir cualquier número y tipo de parámetros. * Como en cualquier otra situación en Java.

. * Se pueden poner tantas cláusulas import como se quieran.: import java.util. Cursos de Verano de Málaga . Capítulo 2: Objetos en Java. Java busca en los directorios en el orden en que éstos se especifiquen en CLASSPATH. y decirle al compilador dónde la debe encontrar. P. S G R * Si queremos utilizar todas las librerías que cuelguen de un subdirectorio concreto se emplea: import java.ej.*.2005 -9- Utilización de componentes p Para reutilizar una clase debemos emplear la palabra clave import.Vector.class que está en el subdirectorio java\util\ * Pero.util. quiere decir que queremos usar Vector.Programación en Java. ¿de dónde cuelga java\util\? Pues Java lo buscará a partir de los directorios que se indiquen en la variable del entorno del sistema operativo llamada CLASSPATH.

ej.i y ts2. // ts1. quiere decir que no está asociado a ningún objeto particular perteneciente a esa clase. Capítulo 2: Objetos en Java.: class TestStatic { static int i = 47. ya que éstos sólo tienen sentido cuando se trabaja con instancias concretas de una clase.i valen lo mismo.i valen lo mismo. * Por el mismo motivo. se puede emplear el propio nombre de la clase.i++. en lugar de utilizar el manejador de un objeto ya creado. esto es 49 * static es la forma de simular funciones (del estilo de las de C). para referenciar un elemento static. } TestStatic ts1 = new TestStatic(). * P. * Dado que una función static no se ejecuta sobre ningún objeto concreto. en un lenguaje orientado a objetos como Java. esto es 47 ts1. .i++.i y ts2. dentro de la misma no se tiene acceso a los elementos no estáticos. // ts1. Cursos de Verano de Málaga .Programación en Java.i y ts2. // Esta es otra forma de referirse a cosas estáticas // ts1.i valen lo mismo. esto es 48 TestStatic. TestStatic ts2 = new TestStatic().2005 -10- Cosas static * Cuando en una clase se dice que algo es estático (un dato o una función miembro).

Math.lang.Math. * En JDK 5 pueden evitarse estas continuas referencias a Math. . pero no se recomienda en aras de una mayor claridad.Math. Ej.lang.. Cursos de Verano de Málaga .lang. double r = Math. o a cualquier otra clase mediante una importación estática.Programación en Java. .Math. de la forma: import static java. double r = cos(PI * tita).PI.cos(Math.lang. De hecho hay que tener cuidado con no importar estáticamente varias clases que comparten un miembro estático con el mismo nombre.*.PI * tita). S G * También pueden importarse todos los miembros estáticos de una sola tacada con: R import static java.. .: import java. import static java.. Capítulo 2: Objetos en Java.cos..2005 -11- Importación estática * Algunas veces se hace un import de una clase con el único objetivo de utilizar alguno de sus miembros estáticos.

java import java.freeMemory()).println(new Date()).println( "Total de memoria = " + rt. Properties p = System. p. . * La clase que se desea ejecutar debe tener una función miembro estática llamada main() que recibe como argumento un array de String.getProperties().util.out. Cursos de Verano de Málaga .list(System.println. System.out). Runtime rt = Runtime.out.2005 -12- El primer programa // Propiedades.*.println("---Uso de memoria:"). * Date es un objeto que se crea con el único objetivo de pasárselo como parámetro a System. Capítulo 2: Objetos en Java. * El signo + indica concatenación cuando se utiliza con cadenas de caracteres. System.Programación en Java. que serán los parámetros que se le pasen desde la línea de comandos. public class Propiedades { public static void main(String[] args) } System.out. * El signo + se puede emplear para concatenar cadenas de caracteres junto con números (automáticamente los números se convierten a su representación textual).getRuntime().out. } } * El primer import mete todas las librerías del directorio java\util\ * System posee un dato miembro estático llamado out que está definido como un objeto del tipo PrintStream.totalMemory() + "Memoria libre = " + rt.

<< >> >>> > < >= <= == != S G R && || & | ^ A > B? X : Y = (y asignaciones compuestas) * Cuando se asignan tipos primitivos. .2005 -13- Operadores Java * Los operadores permitidos por Java son aproximadamente los mismos que los que posee C++. lo que se hacen son copias de los datos concretos. y tienen la precedencia que se especifica a continuación: Mnemónico Ulcer Addicts Really Like C A lot Tipo de operador Unarios Aritméticos y de desplazamiento Relacionales Lógicos Condicional Asignación Operador + .++ -* / % + . * No ocurre lo mismo cuando se trabaja con manejadores de objetos.Programación en Java. Capítulo 2: Objetos en Java. dado que no intervienen manejadores. Cursos de Verano de Málaga . lo que ocurre es que el manejador lvalor referencia al mismo objeto que el manejador r-valor. En estos casos.

j).nextFloat(). j. int i) { prt(s + " = " + i). k. i). i = j .w". u). u = v / w. pInt("j . i). i = k % j. u). public class MathOps { // Create a shorthand to save typing: static void prt(String s) { System. v). i).util. u -= v. 1998.java // Copyright (c) Bruce Eckel. } // shorthand to print a string and a float: static void pFlt(String s. u = v * w.nextFloat(). pFlt("w". i). } } Capítulo 2: Objetos en Java.k).w.Programación en Java. pInt("j + k". pFlt("v / w". k = rand. // '%' limits maximum value to 99: j = rand. // the following also works for char. . u). u). w).k. // Floating-point number tests: float u. u).out. short. i = k * j.2005 -14- Ejemplo de uso de operadores //: MathOps. pFlt("v". // applies to doubles. pInt("k / j". pFlt("u -= v". byte.println(s). pInt("j". j %= k. w = rand. u *= v. u).*.v. long and double: u += v. seeds with current time by default: Random rand = new Random().nextInt() % 100.w. } // shorthand to print a string and an int: static void pInt(String s. u = v . pFlt("u /= v". i = j + k.j). pInt("k * j". i). pInt("k".nextInt() % 100. u). u). pFlt("v . pFlt("u += v". int i. pFlt("v + w". } public static void main(String[] args) { // Create a random number generator. int. i = k / j. pFlt("v * w". float f) { prt(s + " = " + f). pInt("j %= k". pInt("k % j". u = v + w. pFlt("u *= v". Source code file from the book "Thinking in Java" // Demonstrates the mathematical operators import java. u /= v. too v = rand. Cursos de Verano de Málaga .k".

|| y !).Programación en Java. System.out. Cursos de Verano de Málaga . sino si G ambos manejadores se refieren físicamente al mismo objeto.println(n1 != n2). 1998 // Source code file from the book "Thinking in Java" public class Equivalence { public static void main(String[] args) { Integer n1 = new Integer(47).java // Copyright (c) Bruce Eckel.out. System. excepto por el hecho de que no incorporan cortocircuito. no se está preguntando realmente por el contenido de los objetos apuntados.println(n1 == n2). Capítulo 2: Objetos en Java.2005 -15- Comparación e igualdad de objetos //: Equivalence. } } S * Cuando se comparan manejadores. se utiliza el método equals() que debe ser reescrito para cada clase de objetos que se quieran comparar. * Java utiliza cortocircuito en los operadores lógicos. Integer n2 = new Integer(47). | y ~) para valores boolean se comportan igual que los relacionales (&&. . * Los operadores de bit (&. R * Para que funcione bien.

Capítulo 2: Objetos en Java. 1998 // Source code file from the book "Thinking in Java" class Literals { char c = 0xffff. long n1 = 200L. // 10 to the power } * Si se hacen operaciones con valores de tipos más pequeños que el int (char. // Hexadecimal (uppercase) int i3 = 0177. y el resultado es int. // long suffix long n2 = 200l. Cursos de Verano de Málaga .java // Copyright (c) Bruce Eckel. excepto para los boolean. luego para asignar el resultado a algo de tipo más pequeño debe ser de convertido de nuevo. // float suffix float f4 = 1e-45f. // Octal (leading zero) // Hex and Oct also work with long.Programación en Java. float f2 = 1F. byte o short). // max short hex value int i1 = 0x2f. //: Literals. // double suffix double d3 = 47e47d. . // float suffix float f3 = 1f. * Cuidado con las conversiones en que el tipo destino permite reprepresentar un rango de valores más pequeño que el origen.2005 -16- Casting y literales * Java permite cualquier conversión de un tipo primitivo a otro primitivo. // float suffix double d1 = 1d. // 10 to the power float f5 = 1e+9f. // not allowed float f1 = 1. // Hexadecimal (lowercase) int i2 = 0X2F. // max byte hex value short s = 0x7fff. // max char hex value byte b = 0x7f. dichos valores son «promocionados» a int antes de hacer la operación. // long suffix long n3 = 200. //! long l6(200). // double suffix double d2 = 1D.

. break. } La parte default es opcional. . case valor2 : sentencia. break.2005 -17- Sentencias de ctrl. * switch-case switch(selector int) { case valor1 : sentencia. break. de flujo * Las condiciones deben tener siempre un valor de tipo boolean. case valor3 : sentencia. // .. S G R Capítulo 2: Objetos en Java. y si el método debe retornar algún valor. if(expresión boolean) sentencia ó if(expresión boolean) sentencia else sentencia * return Hace que se acabe el método que la ejecuta. dicho valor debe seguir a la sentencia return.Programación en Java. default : sentencia. * if-else. Cursos de Verano de Málaga .

* while(expresión boolean) sentencia * do sentencia while(expresión boolean). continue label1. break.2005 -18- Sentencias de ctrl. // Se sale de iteración_interna .. continue.. continue acaba el ciclo actual y comienza el siguiente..Programación en Java... // Se sale de iteración_externa .. //Hace el siguiente ciclo de iteración_interna . Cursos de Verano de Málaga . de flujo * La sentencia while tiene dos formatos.. . break y continue pueden referenciar a un bucle más externo de aquél en el que se encuentran: label1: iteración_externa { iteración_interna { . según la condición se evalúe antes de entrar al cuerpo del bucle o una vez ejecutado éste.. //Hace el siguiente ciclo de iteración_externa } } Capítulo 2: Objetos en Java. break label1. * break y continue break se sale del bucle en el que se encuentra.

} Capítulo 2: Objetos en Java. * for( sentencias de inicio. while(expresión boolean) { sentencia. y otro para recorrer arrays y colecciones (que se verán más adelante). sentencias de paso. return resultado. sentencias de paso) sentencia equivale a: sentencias de inicio. } S G R : array de tipo ) * for( tipo identificador de muestreo sentencia como por ejemplo: // Devuelve la suma de los elementos de a int suma(int[] a) { int resultado = 0. uno equivalente al del lenguaje C. de flujo * El bucle for tiene dos formatos. . Cursos de Verano de Málaga .Programación en Java. for (int i : a) resultado += i. expresión boolean.2005 -19- Sentencias de ctrl.

Capítulo 3: Inicialización de objetos.out. class Rock { Rock() { // This is the constructor System. Cursos de Verano de Málaga . i < 10. y no retorna ningún tipo (ni siquiera void). i++) new Rock(). //: SimpleConstructor.java // Copyright (c) Bruce Eckel. } } public class SimpleConstructor { public static void main(String[] args) { for(int i = 0.println("Creating Rock"). Constructores * Si una clase tiene un método especial al que se le llama constructor.2005 -1- Capítulo 3 Inicialización de objetos. .Programación en Java. 1998 // Source code file from the book "Thinking in Java" // Demonstration of a simple constructor package c04. para que se pueda ejecutar.class resultante esté en el directorio que se indique. } } S G R * El modificador package obliga a que el fichero SimpleConstructor. * Un constructor es un método especial. Tiene el mismo nombre que la clase a la que pertenece. Java llama automáticamente a este método cada vez que se crea un objeto de esa clase.

println("Creating Rock number" + j). Capítulo 3: Inicialización de objetos.java // Copyright (c) Bruce Eckel. . i++) new Rock(i). i < 10.2005 -2- Constructores con parámetros * Un constructor puede tener parámetros que indiquen cómo hay que crear al objeto. Si el programador crea algún constructor. 1998 // Source code file from the book "Thinking in Java" // Demonstration of a constructor with one argument package c04. Cursos de Verano de Málaga . a través del recolector de basura.Programación en Java.out. class Rock { Rock(int j) { // This is the constructor System. } } * Si el programador no crea ningún constructor. Cuando se crea el objeto hay que pasarle dicho argumento. * El sistema llama automáticamente al método finalize() cuando va a recoger a un objeto como basura. el sistema crea uno por defecto sin parámetros. //: SimpleConstructor. el sistema ya no crea ninguno por defecto. } } public class SimpleConstructor { public static void main(String[] args) { for(int i = 0.

ya sea en longitud y/o en tipos. * A menudo la misma palabra denota acciones distintas.println( "int: " + i + ". siempre y cuando sus listas de parámetros sean distintas. o sea.java // Copyright (c) Bruce Eckel. String: " + s).out. a un trozo de código. 1998 // Source code file from the book "Thinking in Java" // Overloading based on the order of the arguments. int i) { System.out. * Java permite sobrecargar los nombres de los métodos.println( "String: " + s + ". } public static void main(String[] args) { print("String first". print(99. public class OverloadingOrder { static void print(String s. int: " + i). } static void print(int i. o sea. No se puede sobrecargar únicamente sobre el tipo de valor retornado. String s) { System.2005 -3- Sobrecarga de funciones * Un método es el nombre que se le da a una acción. //: OverloadingOrder.Programación en Java. "Int first"). . su significado está sobrecargado. Se distingue un significado de otro a través del contexto. 11). } } S G R Capítulo 3: Inicialización de objetos. Cursos de Verano de Málaga .

util. Cursos de Verano de Málaga .Programación en Java. t. } void info() { prt("Tree is " + height + " meters tall"). } } public class Overloading { public static void main(String[] args) { for(int i = 0. } Tree(int i) { prt("Creating new Tree that is " + i + " meters tall"). i++) { Tree t = new Tree(i).2005 -4- Sobrecarga del constructor * De esta forma. } // Overloaded constructor: new Tree(). Source code file from the book "Thinking in Java" // Demonstration of both constructor and ordinary method overloading.*. class Tree { int height. podemos sobrecargar el constructor de una clase.out. height = 0. Tree() { prt("Planting a seedling").info("overloaded method"). t.println(s). } void info(String s) { prt(s + ": Tree is " + height + " meters tall"). i < 5. import java. . } static void prt(String s) { System. 1998. //: Overloading.java // Copyright (c) Bruce Eckel. height = i.info(). } } Capítulo 3: Inicialización de objetos.

. pero no hace falta.: class Ciruela { void coger() { /*. Capítulo 3: Inicialización de objetos.java // Source code file from the book "Thinking in Java" // Simple use of the this keyword public class Leaf { private int i = 0. * Cuando desde un método de una clase se llama a otro método de la misma clase. Cursos de Verano de Málaga . } public static void main(String[] args) { Leaf x = new Leaf().2005 -5- La palabra clave this * La palabra clave this se emplea dentro de un método como manejador al objeto que recibe el mensaje. Leaf increment() { i++.out. } void print() { System. } } S G R * Ahora se comprende mejor qué es un método static: es aquél en el que this no tiene sentido.increment().*/ } } /* Dentro de comer() se podría haber hecho this. Se supone por defecto. /*.println("i = " + i). . return this.increment(). x.increment().coger().. */ * Ejemplo: //: Leaf..print().*/ } void comer() { coger(). Ej.Programación en Java. no hace falta poner this.. ya que por defecto se supone.

Programación en Java. Capítulo 3: Inicialización de objetos. * Un constructor sólo puede llamar a otro una vez. para evitar repetir código. * this también se puede utilizar para distinguir entre los nombres de los parámetros y los de los campos. debe ser la primera acción que haga. * La palabra this dentro de un constructor permite hacer llamadas a otros constructores. Cursos de Verano de Málaga . Ej.: * Si un constructor llama a otro.2005 -6- Llamada a un constructor desde otro constructor * Cuando se ha sobrecargado el constructor. . hay veces en que puede ser conveniente llamar a un constructor desde otro.

petalCount= " + petalCount). } Flower(String s.print(). // Can't call two! this. System. // Not inside non-constructor! System.java // Copyright (c) Bruce Eckel. s=" + ss). } Flower(String ss) { System. } public static void main(String[] args) { Flower x = new Flower().println("Constructor w/ String arg only.println("String and int args").Programación en Java. // Another use of this System.s = s. } void print() { //! this(11). . s = ss.out. int petals) { this(petals). 1998 // Source code file from the book "Thinking in Java" // Calling constructors with this public class Flower { private int petalCount = 0. x. private String s = new String("null").out. 47).println("petalCount = " + petalCount + " s = "+ s). } Flower() { this("hi". } } S G R Capítulo 3: Inicialización de objetos.println("Constructor w/ int arg only.out.out. Cursos de Verano de Málaga . Flower(int petals) { petalCount = petals.out. System. //! this(s).println("default constructor (no args)").2005 -7- Uso de this en un constructor //: Flower.

} Capítulo 3: Inicialización de objetos.out. static SuperCopa b4 = new SuperCopa(4).println("f3(" + marker + ")"). Cursos de Verano de Málaga . t2.out.out.f3(1). t3.println("Creating new Liga() in main"). } void f(int marker) { System.println("Creating new Liga() in main"). } } class Tabla { static SuperCopa b1 = new SuperCopa(1).println("Liga()").out. } static SuperCopa b5 = new SuperCopa(5). } public class StaticInitialization { public static void main(String[] args) { System. class SuperCopa { SuperCopa(int marker) { System.f2(1).println("SuperCopa(" + marker + ")").Programación en Java. Tabla() { System.out.out.f(1). new Liga(). b4.println("f(" + marker + ")"). System.f(2).java // Specifying initial values in a class definition. Liga() { System. } class Liga { SuperCopa b3 = new SuperCopa(3).out.out. static Liga t3 = new Liga(). } static SuperCopa b2 = new SuperCopa(2). b2. } void f2(int marker) { System.println("Tabla()").2005 -8- Inicialización de datos estáticos * Adivinar el resultado de lo siguiente: //: StaticInitialization. } void f3(int marker) { System.println("f2(" + marker + ")"). } static Tabla t2 = new Tabla(). new Liga(). .

} } public class Corderos { Cordero c1. Cordero c2.println("f(" + marker + ")"). Corderos x = new Corderos(). . } void f(int marker) { System. c2 = new Cordero(2). { c1 = new Cordero(1). */ i = 47. aunque no sean estáticos.println("Corderos()"). 1998 // Source code file from the book "Thinking in Java" // Java 1.out. } } * En Java se pueden inicializar los datos miembros de un objeto. static { /* Aquí va el código que se ejecutará en cuanto se cargue la clase.2005 -9- Sobrecarga del constructor * Java permite colococar un código de inicialización de la clase.println("c1 & c2 initialized"). } public static void main(String[] args) { System. } } S G R Capítulo 3: Inicialización de objetos.out. System.out.out. } Corderos() { System. Cursos de Verano de Málaga . Esto se hace precediendo el trozo de código de la palabra static: class Prueba { int i.println("Inside main()").Programación en Java.1 "Initialización de objetos" class Cordero { Cordero(int marker) { System. En el siguiente ejemplo se omite la palabra static: //: Mugs.java Copyright (c) Bruce Eckel.println("Cordero(" + marker + ")").out.

s[0] = new String("Posición 1"). 7. . excepto por el hecho de que en la declaración no se indica el tamaño. s[1] = new String("Posición 2"). Puede hacerse de dos formas: .2005 -10- Inicialización de arrays * En Java un array es un objeto.ej. int a[] = {1. String s[] = new String[3]. El array debe ser creado posteriormente. P. 4. * Cuando se declara un array en realidad estamos declarando un manejador a un array. * Las dimensiones que están al mismo nivel no tienen porqué tener la misma longitud. a[0] = new int[5]. int[] a. * Los arrays se declaran como en C. 5. int b[]. s[2] = new String("Posición 3").Enumerando el valor de sus elementos entre llaves en el momento de la declaración. a[2] = new int[7]. int a[] = new int[10].Mediante el new correspondiente. . 3 . Esto lleva implícito el new. Capítulo 3: Inicialización de objetos. 2. // La última coma es opcional * Un array de objetos es en realidad un array de manejadores. * El primer elemento de un array está en la posición 0. como para cualquier otro objeto.Programación en Java.: int[][] a = new int[3][]. 6. Cursos de Verano de Málaga . * En Java no existen arrays multidimensionales. b = new int[7]. a[1] = new int[13].}. sino arrays de arrays cuantas veces se quiera.

11) }).14). i < x. for(int i = 0. new A(). } public static void main(String[] args) { int[] a. S G inicializar R } en el momento de la Integer[] b = new Integer[] { new Integer(1). a[0][1] vale 13. new A()}). i++) System. * El número de elementos que va a poseer un array no tiene porqué conocerse en tiempo de compilación.length).out.util. i++) prt("a[" + i + "] = " + a[i]). "three" }).abs(rand. new VarArgs(). }. } } Capítulo 3: Inicialización de objetos. Ej. prt("length of a = " + a.println(x[i]).length.: //: VarArgs. new Integer(2). new Integer(3). Cursos de Verano de Málaga . new Float(3. Ej. }.Programación en Java. f(new Object[] {new A(). public class ArrayNew { static Random rand = new Random(). a = new int[pRand(20)]. f(new Object[] {"one". new Integer(2).println(s). .java // Copyright (c) Bruce Eckel. import java. en conjunción con que todo objeto hereda tarde o temprano de Object permite crear métodos en los que el número de argumentos es variable. static int pRand(int mod) { return Math. i < a.length. } public static void main(String[] args) { f(new Object[] { new Integer(47). "two". En el caso anterior.java // Copyright (c) Bruce Eckel.nextInt()) % mod + 1.*. new Double(11. * La segunda forma de inicialización.: //: ArrayNew. } public class VarArgs { static void f(Object[] x) { for(int i = 0.out.1 array syntax // to create variable argument lists class A { int i. } * Hay dos formas de declaración: Integer[] a = { new Integer(1). 1998 /* Source code file from the book "Thinking in Java" */ // Creating arrays with new. 1998 // Using the Java 1.2005 -11- Inicialización de arrays * El número de elementos de un array viene dada por un dato miembro que se llama length. new Integer(3). } static void prt(String s) { System.

Programación en Java. Cursos de Verano de Málaga - 2005

-12-

Número variable de argumentos
* En JDK 5 la invocación anterior se podría haber hecho igualmente declarando la función f de la forma: static void f( Object ... x ) que es traducida automáticamente por el compilador a: static void f( Object[] x ) * Las llamadas de la forma f(arg1, arg2, argn) se traducen automáticamente por el compilador a: f(new Object[]{f(arg1, arg2, argn}); por lo que está claro que los puntos suspensivos sólo pueden ser el último argumento de una función. * Haciendo uso de este mecanismo, Java 5 incorpora en el objeto System.out la función printf que permite emitir una salida formateada al estilo de C. Por ejemplo: System.out.printf( “Hay %d planetas en el sistema %s.%n”, numeroPlanetas, nombreSistema ); * Para conocer más acerca del formato de los mensajes en un printf debe estudiarse la clase Formatter del paquete java.util.

Capítulo 3: Inicialización de objetos.

Programación en Java. Cursos de Verano de Málaga - 2005

-1-

Capítulo 4 Reutilización de código
* Antes de ver conceptos para la reutilización de código, es necesario estudiar los elementos que nos da Java para distribuir el código, y para establecer la interfaz de cada clase. * package. Un paquete es lo que cogemos cuando ponemos en nuestro programa una sentencia como: import java.util.*; Esto accede al subdirectorio java\util\ y pone a nuestra disposición todos los *.class que haya allí. O sea, un paquete es el conjunto de ficheros *.class que está en un mismo subdirectorio. NOTA: Java utiliza el punto (.) como separador de subdirectorios, y posteriormente lo sustituye por \ ó / según el sistema operativo (DOS ó Unix).

S G R

* Cuando se crea un fichero File.java (también llamado unidad de compilación), este fichero debe contener: Obligatoriamente: -Una clase pública (public) con el mismo nombre que el fichero (quitando el .java). Opcionalmente: - Cualesquiera otras clases, que no pueden ser públicas. * Cuando se compila el fichero File.java se genera un fichero .class por cada una de las clases que contuviera File.java.

Capítulo 4: Reutilización de código.

Programación en Java. Cursos de Verano de Málaga - 2005

-2-

Package
* package es una directiva que (si se emplea) indica donde se van a colocar los .class resultantes de la compilación. * package obliga a que los .class generados deban estar en el directorio especificado para su correcta ejecución.

* Como resultado de hacer un proyecto grande, podemos obtener cientos de clases. Para evitar tener cientos de ficheros, Java permite agruparlos en un fichero .zip sin comprimir, siempre que internamente se mantenga la estructura interna de subdirectorios. * Si cuando se accede al fichero .class, para proceder a su ejecución, en el mismo directorio está su fichero fuente .java, el propio motor de ejecución comprueba las fechas de creación, y si el fuente es más reciente que el .class, se recompila el fuente en tiempo de ejecución, obteniéndose un .class actualizado que, entonces, se ejecuta.
Capítulo 4: Reutilización de código.

Programación en Java. Cursos de Verano de Málaga - 2005

-3-

Los ficheros .jar Paquetes y colisiones
* Las clases que componen nuestro proyecto también se pueden agrupar comprimidos en un fichero .jar, a través de la utilidad Java, jar.exe. Un fichero .jar, a diferencia de uno .zip, posee las siguientes características: - Comprime de verdad los ficheros que contiene. - Puede contener cualquier tipo de fichero, además de los .class. - Se transfiere entero en operaciones a través de la red. * Los ficheros .jar y .zip deben declararse explícitamente en la variable del entorno CLASSPATH. En Java 2 también basta con meterlos en el directorio jdk1.3\jre\lib\ext, reservado para las extensiones de las librerías de Java.

S G R * En esta variable se colocan además los directorios base en los
que se desea que Java busque cuando se quiere importar una librería o una clase concreta. * Se produce una colisión cuando se importan dos paquetes, que poseen una clase con el mismo nombre, y además se hace uso de dicha clase.

* Cuando se ejecuta un .class que no forma parte de ningún paquete, Java asume que ese directorio conforma el paquete por defecto para esa clase. * Es un buen momento para ver la tabla de accesibilidad del capítulo 1.
Capítulo 4: Reutilización de código.

Programación en Java. Cursos de Verano de Málaga - 2005

-4-

Visibilidad
* Hay dos motivos para restringir al exterior el acceso a los miembros de una clase: 1.- Que los que usan dicha clase no tengan acceso a cosas que no deben tocar. O sea, cosas que forman parte de las «tripas» de la clase, pero que al usuario no le interesan para nada, y que no forman parte de la interfaz de la clase. Para el usuario también supone un alivio porque así no se pierde en un mar de detalles que no le interesan. 2.- Permitir al diseñador de la clase cambiar la implementación sin que por ello los programas del usuario se tengan que modificar. El usuario se limita a emplear la interfaz, sin importarle para nada los detalles de implementación.

Capítulo 4: Reutilización de código.

} } public class SprinklerSystem { private String valve1. } public String toString() { return s.java Copyright (c) Bruce Eckel.out. int i.2005 -5- Composición * Como vimos en su momento hay dos formas de reutilizar código.out. s = new String("Constructed"). valve2. } public static void main(String[] args) { SprinklerSystem x = new SprinklerSystem().out.out.out. valve3.println("source = " + source). x.Programación en Java.println("f = " + f). System. WaterSource() { System.print(). 1998 // Source code file from the book "Thinking in Java" // Composition for code reuse package c06. System. WaterSource source = new WaterSource(). float f.out.out. Este método se llama toString(). System. System.println("valve3 = " + valve3). void print() { System. es necesario que posea un método que lo convierta en String. La primera consiste en meter objetos dentro de otros objetos. Capítulo 4: Reutilización de código. System.println("valve4 = " + valve4). y debe retornar un String. Es algo así como crear un registro.println("valve1 = " + valve1). System. //: SprinklerSystem.println("i = " + i).out.println().println("WaterSource()"). class WaterSource { private String s.println("valve2 = " + valve2). valve4.out. } } S G R * Para poder visualizar un objeto de la clase WaterSource con System. . Cursos de Verano de Málaga .

x.diluir(). } public static void main(String[] args) { Limpiador x = new Limpiador(). super.2005 -6- Herencia * Este es el método básico de reutilización de código en la programación O.out. Tanto en uno como en otro caso. } // Test the new class: public static void main(String[] args) { Detergente x = new Detergente().aplicar(). x. x.lavar(). } public void aplicar() { append(" aplicar()"). * La herencia permite crear clases que son parecidas a otra clase base y que.println(s).out.main(args). public void append(String a) { s += a. .diluir(). para heredar se emplea la palabra clave extends. x.esperar()"). // Call base-class version } // Add methods to the interface: public void lavar() { append(" lavar()"). } } Capítulo 4: Reutilización de código. 1998 // Source code file from the book "Thinking in Java" // Inheritance syntax & properties class Limpiador { private String s = new String("Limpiador"). } public void diluir() { append(" diluir()"). System. extender funcionalmente a la clase base. si quieren.esperar(). pueden tener más métodos. Cursos de Verano de Málaga . x. Limpiador. } } public class Detergente extends Limpiador { // Change a method: public void esperar() { append(" Detergente.print().O.println("Testing base class:").Programación en Java.print(). } public void print() { System.aplicar(). //: Detergente. x. o sea. x.java Copyright (c) Bruce Eckel. } public void esperar() { append(" esperar()"). x. x.esperar().esperar().

que se refiere a la superclase. no pueden ser públicas. .. a través de la palabra clave super.Cuando se invoca la ejecución con java Detergente. 9.. 2. 4.Programación en Java..2005 -7- Herencia * El ejemplo anterior nos ilustra muchas cosas: 1.Dado que Detergente hereda de Limpiador....java.El operador += está sobrecargado para los String.. 3... 8.Si hay otras clases.Tanto Limpiador como Detergente poseen un public static void main().La clase base se puede extender con nuevos métodos y/o miembros (lavar()). Esto permite comprobar de forma independiente cada una de las clases con pocos cambios en el fichero . 7. R 6. Cursos de Verano de Málaga . Capítulo 4: Reutilización de código.En la clase hija es posible reescribir un método que ya estaba en la clase padre (esperar()).La clase que tiene el mismo nombre que el fichero (Detergente) tiene que ser pública. S 5. hereda automáticamente todos sus miembros.Java permite llamar a un método de la clase padre (aunque esté reescrito). sólo se G ejecuta el main() de dicha clase.

public: indica que cualquiera tiene acceso a ese miembro. -nada-: Sólo tienen acceso las clases hijas. En el caso anterior Miembro 3 es público. Miembro 2 es protected. protected: indica que las clases hijas tienen acceso a él. pero que no es visible para nadie más. pero el usuario de dicha clase sólo deba ver la interfaz de la nueva clase. * Se empleará composición cuando se quiera crear una clase nueva. lo cual quiere decir que Hija tiene acceso a él. Cursos de Verano de Málaga . y no la del objeto componente. Capítulo 4: Reutilización de código. * Vamos a explicar de nuevo los modificadores de visibilidad.Programación en Java. . podemos hacernos una idea de qué es un objeto hijo. private: Nadie tiene acceso (a no ser que también se indique protected). y con la siguiente figura en mente. y las clases del mismo paquete. No así con la herencia.2005 -8- Visibilidad * Ahora que sabemos cómo funciona la herencia.

out. //: Cartoon. es necesario que la clase base inicialice las «tripas» de aquello a lo que no tiene acceso la clase hija.out. Por ello. . Cursos de Verano de Málaga .println("Drawing constructor").2005 -9- Inicialización en herencia * Para que el constructor de las clases hijas tenga sentido. } } public class Cartoon extends Drawing { Cartoon() { System.println("Art constructor").java Copyright (c) Bruce Eckel. Java inserta automáticamente un llamada al constructor por defecto (el que no tiene parámetros) de la clase base. } } class Drawing extends Art { Drawing() { System.Programación en Java. } public static void main(String[] args) { Cartoon x = new Cartoon(). justo antes de hacer cualquier otra cosa en el constructor de la hija.out. 1998 // Source code file from the book "Thinking in Java" // Constructor calls during inheritance class Art { Art() { System.println("Cartoon constructor"). } } S G R Capítulo 4: Reutilización de código.

} } public class Chess extends BoardGame { Chess() { super(11). 1998 // Source code file from the book "Thinking in Java" // Inheritance. .Programación en Java.java Copyright (c) Bruce Eckel. } } class BoardGame extends Game { BoardGame(int i) { super(i). Cursos de Verano de Málaga . } } Capítulo 4: Reutilización de código.println("BoardGame constructor"). Para ello se hace uso de la palabra super.2005 -10- Inicialización en herencia * Si la clase padre no tiene constructor sin parámetros. lo primero que debe hacer el constructor de la clase hija es una llamada a uno de los constructores parametrizados de la clase padre.out.out. constructors and arguments class Game { Game(int i) { System.out.println("Game constructor"). System. //: Chess. System. } public static void main(String[] args) { Chess x = new Chess().println("Chess constructor").

println( "PlatoParaCenar constructor").println( "PlaceSetting constructor"). } } class Cuchillo extends Utensilio { Cuchillo(int i) { super(i).out.out. } } S G R Capítulo 4: Reutilización de código. .out. pl = new PlatoParaCenar(i + 5). Cuchillo kn. } public static void main(String[] args) { PlaceSetting x = new PlaceSetting(9). 1998 /* Source code file from the book "Thinking in Java" */ // Combining composition and inheritance class Plato { Plato(int i) { System.Programación en Java. } } public class PlaceSetting extends Custom { Cuchara sp.out.out.2005 -11- Composición y herencia * Predecir el resultado de: //: PlaceSetting. sp = new Cuchara(i + 2). System. } } class Utensilio { Utensilio(int i) { System. System. } } class Custom { Custom(int i) { System. PlaceSetting(int i) { super(i + 1).out.println("Cuchillo constructor").println("Tenedor constructor").println("Custom constructor").out. } } class Tenedor extends Utensilio { Tenedor(int i) { super(i).java // Copyright (c) Bruce Eckel.out.println("Plato constructor"). } } class PlatoParaCenar extends Plato { PlatoParaCenar(int i) { super(i). kn = new Cuchillo(i + 4). PlatoParaCenar pl.println("Cuchara constructor"). System. Cursos de Verano de Málaga . frk = new Tenedor(i + 3). } } class Cuchara extends Utensilio { Cuchara(int i) { super(i). Tenedor frk. System. System.println("Utensilio constructor").

1998 // Source code file from the book "Thinking in Java" // Inheritance & upcasting import java.. } } // InstrumentoDeViento objects are Instrumentos // because they have the same interface: class InstrumentoDeViento extends Instrumento { public static void main(String[] args) { InstrumentoDeViento flauta = new InstrumentoDeViento().java // Copyright (c) Bruce Eckel. Al proceso automático que convierte de InstrumentoDeViento en Instrumento. ..util. Cursos de Verano de Málaga . ya que las clases hijas siempre tienen que tener como mínimo todas las operaciones de la clase padre.play().*.2005 -12- Upcasting * Una de las características más importantes de la herencia. Capítulo 4: Reutilización de código. class Instrumento { public void play() {} static void tune(Instrumento i) { // . // Upcasting } } * Si tune() funciona para Instrumentos. es que un objeto hijo se puede emplear en cualquier lugar donde se espere un objeto padre. //: InstrumentoDeViento. Instrumento.Programación en Java. también debe funcionar para cualquier cosa que herede de Instrumento. se le llama upcasting.tune(flauta). * Upcasting es una acción segura. i.

S .Clases. Quiere decir que nadie puede heredar de esta clase. Es una forma de identificar a los valores primitivos constantes. Evita que cualquier clase hija lo pueda reescribir. Esta palabra clave puede preceder a: .Métodos. Capítulo 4: Reutilización de código. sin embargo el objeto en sí. R .Datos miembro. Que un dato miembro sea final no quiere decir que su valor se conozca en tiempo de compilación. Quiere decir que el parámetro es de G solo lectura. A un dato miembro final se le puede asignar un valor en el momento de su declaración. Además permite al compilador javac convertir las llamadas a dicho método en código inline. Si el dato miembro es un manejador de objetos. . quiere decir que ese manejador siempre apuntará al mismo objeto físico.Programación en Java.2005 -13- La palabra clave final * final viene a decir: «Esto es inalterable». o una sola vez en el cuerpo de cualquier método. .Parámetros de función. sí puede ser modificado. Cursos de Verano de Málaga .

tocar()").println("Instrumento. } public static void main(String[] args) { InstrumentoDeViento flauta = new InstrumentoDeViento(). } public static final Nota mediaFa = new Nota(0).java // Copyright (c) Bruce Eckel.out. //: Musica. class Instrumento { public void tocar(Nota n) { System.println("InstrumentoDeViento.tocar()"). Capítulo 4: Reutilización de código.out.out. private Nota(int val) { valor = val. } } // InstrumentoDeCuerda objects are Instrumentos because they have the same interface: class InstrumentoDeCuerda extends Instrumento { // Redefine interface method: public void tocar(Nota n) { System. Instrumento guitarra = new InstrumentoDeCuerda(). } } public class Musica { public static void Afinar(Instrumento i) { i.2005 -14- Polimorfismo * El polimorfismo o vinculación dinámica permite distinguir entre objetos de clases distintas que heredan de una misma clase base.mediaFa). 1998 // Inheritance & upcasting package c07. . } } // InstrumentoDeViento objects are Instrumentos because they have the same interface: class InstrumentoDeViento extends Instrumento { // Redefine interface method: public void tocar(Nota n) { System. FaGrave = new Nota(2).Programación en Java.tocar(Nota. class Nota { private int valor. InstrumentoDeCuerda piano = new InstrumentoDeCuerda(). Instrumento maracas = new Instrumento().println("InstrumentoDeCuerda. Cursos de Verano de Málaga .tocar()"). FaAguda = new Nota(1). } // Etc.

* Aquí se emplea el upcast para «olvidar» intencionadamente el tipo concreto de un objeto. o sea. se producirá lo que se llama vinculación dinámica. para que esto funcione hay que hacer un enorme switch en el que se pregunta por todos y cada uno de los tipos posibles. * Cuando se llame a uno de sus métodos. De esta forma. se llama al método de la clase a que pertenezca verdaderamente el objeto manejado. // Upcasting Afinar(maracas).2005 -15- Polimorfismo Afinar(flauta). // Upcasting } } * Si observamos el resultado. lo que «suena» es cada instrumento concreto. * En otros lenguajes de programación.Programación en Java.. . tratarlo como si fuera un Instrumento cualquiera (con la interfaz de Instrumento). el manejador de Instrumentos pasa a ser polimórfico en el sentido de que puede controlar no sólo Instrumentos sino cualquier objeto que herede de Instrumento. InstrumentoDePercusion). vemos que en el momento en que se llama a afinar(). S * El método de Java tiene laG ventaja de que si se inserta un nuevo instrumento (p. Cursos de Verano de Málaga . todos los objetos pasan a ser manejados por un manejador de Instrumento. // Upcasting Afinar(piano). Sin embargo. cuando en afinar() se llama a tocar(). // Upcasting Afinar(guitarra). no es R de las clases que ya están necesario modificar el código construidas. Capítulo 4: Reutilización de código.ej.

case 1 : return new InstrumentoDeCuerda(). } } public static void main(String[] args) { Instrumento[] ai = new Instrumento[10].java // No se sabe de qué tipo será cada Instrumento package c07. .nextInt() % 3) { case 0 : return new InstrumentoDeViento(). } } } Capítulo 4: Reutilización de código.2005 -16- Polimorfismo * Cuando se llama a afinar(). class InstrumentoDePercusion extends Instrumento { // Redefine interface method: public void tocar(Nota n) { System.util. Musica. * Podemos ponérselo más complicado al sistema con el siguiente programa. y deja que el sistema vincule dinámicamente (en tiempo de ejecución) cada objeto con su verdadero método. afinar() llama a tocar().tocar()"). // Dificil. import java.out. pero no se sabe de qué tipo. } } public class Dificil { public static Instrumento randInstrumento() { switch(new Random(). se sabe que se tiene un Instrumento. i++) ai[i] = randInstrumento().Programación en Java.*. Cursos de Verano de Málaga . default : return new InstrumentoDePercusion(). i< 10. for(int i=0.println("InstrumentoDePercusion.afinar(ai[i]).

2005 -17- La palabra reservada abstract * Una clase abstracta es aquella que posee al menos un método abstracto. * Debido a esta carencia. * También es posible definir una clase abstracta sin que posea métodos abstractos. R automáticamente se convierten también en abstractas.Programación en Java. Si no lo hacen. y ver los mensajes de error de compilación. El efecto es el mismo. * Un método abstracto es aquél que está declarado. Capítulo 4: Reutilización de código. pero que no posee implementación alguna. Está incompleto.: Hacer que Instrumento sea abstracta. Cursos de Verano de Málaga . ¿Para qué sirve entonces una clase abstracta? S * Una clase abstracta sirve para establecer un marco de trabajo que deben cumplir todas las G clases que hereden de ella. Las clases que heredan de ella sí deben dotar de una implementación a los métodos abstractos del padre. . es imposible declarar objetos de una clase abstracta. Ello se hace anteponiendo abstract a la declaración de la clase. anteponiendo abstract antes de la declaración del método. * Ej.

Programación en Java. Cursos de Verano de Málaga - 2005

-18-

Interfaces
* Una interface es parecida a una clase abstracta excepto porque: - En la interface todas las funciones miembro son implícitamente abstract y public. - En la interface sólo pueden aparecer funciones miembro, y no datos miembro (excepto static final). - Una clase no puede extender una interfaz (extends), sino que la implementa (implements). - Una clase puede implementar tantas interfaces como quiera, pero sólo puede extender una clase. * La interface hace que todas las clases que la implementan tengan un comportamiento semejante. Ej.:
// Prueba.java // Ejemplo de uso de las interfaces import java.io.*; /** @author Sergio Gálvez Rojas */ interface Comparable { boolean mayor(Object o); boolean menor(Object o); boolean igual(Object o); } class Caja implements Comparable { int lado; Caja(int l) {lado = l;} public boolean mayor(Object c) { return lado > ((Caja)c).lado; }; public boolean menor(Object c) { return lado < ((Caja)c).lado; }; public boolean igual(Object c) { return lado == ((Caja)c).lado; }; } class Televisor implements Comparable { int pulgadas; boolean color; Televisor(int p, boolean c) {pulgadas = p; color = c;} public boolean mayor(Object t) { return pulgadas > ((Televisor)t).pulgadas; }; public boolean menor(Object t) { return pulgadas < ((Televisor)t).pulgadas; }; public boolean igual(Object t) { return pulgadas == ((Televisor)t).pulgadas && color == ((Televisor)t).color; } }

Capítulo 4: Reutilización de código.

Programación en Java. Cursos de Verano de Málaga - 2005

-19-

Interfaces
public class Prueba { public static void main(String[] args) { Caja c1 = new Caja(5); Televisor t1 = new Televisor(21, true); Caja c2 = new Caja(15); Televisor t2 = new Televisor(21, false); Caja c3 = new Caja(25); Televisor t3 = new Televisor(28, true); System.out.println("c1 > c2: " + c1.mayor(c2)); System.out.println("c2 < c3: " + c2.menor(c3)); System.out.println("c3 == c2: " + c3.igual(c2)); System.out.println("c3 > c2: " + c3.mayor(c2)); System.out.println("c1 == c1: " + c1.igual(c1)); System.out.println("c1 > c1: " + c1.mayor(c1)); System.out.println("t1 > t2: " + t1.mayor(t2)); System.out.println("t2 == t1: " + t2.igual(t1)); System.out.println("t2 > t1: " + t2.mayor(t1)); } }

* Ej. de implementación de múltiples interfaces:
//: Adventure.java // Copyright (c) Bruce Eckel, 1998 // Source code file from the book "Thinking in Java" // Multiple interfaces import java.util.*; interface CanFight { void fight(); } interface CanSwim { void swim(); } interface CanFly { void fly(); } class ActionCharacter { public void fight() {} } class Hero extends ActionCharacter implements CanFight, CanSwim, CanFly { public void swim() {} public void fly() {} }

S G R

Capítulo 4: Reutilización de código.

Programación en Java. Cursos de Verano de Málaga - 2005

-20-

Interfaces
public class Adventure { static void t(CanFight x) { x.fight(); } static void u(CanSwim x) { x.swim(); } static void v(CanFly x) { x.fly(); } static void w(ActionCharacter x) { x.fight(); } public static void main(String[] args) { Hero i = new Hero(); t(i); // Treat it as a CanFight u(i); // Treat it as a CanSwim v(i); // Treat it as a CanFly w(i); // Treat it as an ActionCharacter } }

* Una interfaz puede heredar de otra interfaz, aunque con el único objetivo de incrementar el número de métodos miembro. * Aunque no pueden crearse objetos de clases abstractas, y mucho menos de interfaces, sí es posible crear manejadores, a los que se puede «enchufar» cualquier objeto de verdad que extienda la clase abstracta, o implemente la interfaz.

Capítulo 4: Reutilización de código.

Programación en Java. Cursos de Verano de Málaga - 2005

-21-

Clases internas
* En Java es posible definir una clase dentro de otra. Dicha clase (llamada clase interna), tiene completa visibilidad sobre los miembros de su clase contenedora. Ej.:
//: Parcel1.java // Copyright (c) Bruce Eckel, 1998 // Source code file from the book "Thinking in Java" import java.io.*; public class Parcel1 { private int j = 23; class Contents { private int i = 11; public int value() { return i; } } class Destination { private String label; Destination(String whereTo) { label = whereTo; } // Aquí accedemos a un miembro private de la clase contenedora. String readLabel() { return label + " " + j; } } // Using inner classes looks just like using any other class, within Parcel1: public void ship(String dest) { Contents c = new Contents(); Destination d = new Destination(dest); System.out.println(d.readLabel()); } public static void main(String[] args) { Parcel1 p = new Parcel1(); p.ship("Tanzania"); } }

S G R

Capítulo 4: Reutilización de código.

Programación en Java. Cursos de Verano de Málaga - 2005

-22-

Clases internas
* Se puede crear una clase interna anónima. Para ello, en el momento en que se crea el objeto se le dota de una nueva implementación. En el siguiente ejemplo se crea un objeto que hereda de una interface, y se le dota de implementación en el mismo momento de su creación. * Para manejar dicho objeto, se utiliza un manejador de objetos que cumplen la interfaz Contents.
//: Parcel6.java // Copyright (c) Bruce Eckel, 1998 // Source code file from the book "Thinking in Java" // A method that returns an anonymous inner class import java.io.*; interface Contents { int value(); } public class Parcel6 { public Contents cont() { return new Contents() { private int i = 11; public int value() { return i; } }; // Semicolon required in this case } public static void main(String[] args) { Parcel6 p = new Parcel6(); Contents c = p.cont(); System.out.println(c.value()); } }

Capítulo 4: Reutilización de código.

Se inicializan los miembros de Círculo en el mismo orden en que están declarados.Se llama al constructor de la clase hija.2005 -23- Polimorfismo y constructores * Probar el siguiente ejemplo: //: PruebaFigura. } } S G R * Esto se debe a que un objeto Círculo se inicializa así: 1..draw().java // Copyright (c) Bruce Eckel.println("Circulo. . Capítulo 4: Reutilización de código. Aquí. } } class Circulo extends Figura { int radio = 1. se llama a draw().out. Cursos de Verano de Málaga .out. ¡Pero ¿qué valor tiene radio en este momento?! 3. 4.Circulo(). draw().out.Programación en Java. Figura() { System.. radio = " + radio). radio = " + radio).println("Circulo. } void draw() { System..Se ubica memoria para un Círculo y se pone toda a cero. abstract class Figura { abstract void draw().println("Figura() before draw()"). Circulo(int r) { radio = r. que como está reescrito. System. System.. 1998 // Source code file from the book "Thinking in Java" // Constructors and polymorphism don't produce what you might expect. por vinculación dinámica es el draw() de Círculo. 2. } } public class PruebaFigura { public static void main(String[] args) { new Circulo(5).out.Se llama al constructor de la clase base Figura.println("Figura() after draw()").

Se hace anteponiendo al nombre del manejador el nombre de la clase hija. Java testea en tiempo de compilación que los downcasting sean correctos. Cursos de Verano de Málaga . Si no lo es se genera la excepción ClassCastException. * Por downcasting se entiende especificar que un manejador de una clase padre está apuntando a un objeto de una clase hija. .Programación en Java. porque se tiene asegurado que un objeto hijo implementa como mínimo todas las operaciones de uno padre. Capítulo 4: Reutilización de código. El único problema es que desde el manejador no se tiene acceso a las extensiones del objeto apuntado.2005 -24- Downcasting * Hacer upcasting es una operación segura.

Programación en Java. new MoreUseful() }. Cursos de Verano de Málaga . 1998 // Source code file from the book "Thinking in Java" // Downcasting & Run-Time Type Identification (RTTI) import java.java // Copyright (c) Bruce Eckel. // Compile-time: method not found in Useful: //! x[1]. // Downcast/RTTI ((MoreUseful)x[0]). x[1]. // Exception thrown } } S G R Capítulo 4: Reutilización de código.f().u(). x[0].g(). . class Useful { public void f() {} public void g() {} } class MoreUseful extends Useful { public void f() {} public void g() {} public void u() {} public void v() {} public void w() {} } public class RTTI { public static void main(String[] args) { Useful[] x = { new Useful(). y los peligros del downcasting.*. ((MoreUseful)x[1]).2005 -25- Downcasting y RTTI * El siguiente ejemplo ilustra las limitaciones del upcasting.u(). //: RTTI.util.u().

se obtiene un RuntimeException. lo que sale es un Object: se ha perdido toda la información referente al tipo.Programación en Java. se guarden también Circulos. G tarde o temprano. Cuadrados. excepto tipos primitivos. Stack. . Como. pues son capaces de almacenar cualquier cosa. Capítulo 5: Colecciones. S * Estas colecciones almacenan objetos de tipo Object. R ya que no pertenecen a clase alguna. dado que se puede guardar cualquier cosa que herede de Object. cualquier clase hereda de Object.2005 -1- Capítulo 5 Colecciones * Cuando se desea tener una gran cantidad de objetos se usan los arrays. * Cuando el número de elementos a almacenar es desconocido se emplean las colecciones. Cursos de Verano de Málaga . Esto presenta dos problemas: . es necesario hacer un cast. cuando se extrae un elemento. tales como Vector. Para recuperarla. p. .Aunque se pretenda guardar elementos homogéneos. por descuido.2. En la versión 1.ej. y Bitset. Hashtable.Como la colección guarda manejadores de Object. que son estructuras dinámicas de datos. se incrementan las posibilidades. * Si uno viola los límites de un array. nada impide que.

*.out. } } class Dog { private int dogNumber. Dog(int i) { dogNumber = i. } void print() { System. Lo extrae como Object.java // Copyright (c) Bruce Eckel. i++) cats.Programación en Java. for(int i = 0. . luego hay que hacerle casting.size().println("Cat #" + catNumber). Añade un elemento. // Not a problem to add a dog to cats: cats. .println("Dog #" + dogNumber). i < cats.print(). Cursos de Verano de Málaga .addElement(new Cat(i)).addElement().util.elementAt(i)). Devuelve el número de elementos en el Vector. Cat(int i) { catNumber = i.2005 -2- Vectores //: CatsAndDogs. Extrae el elemento de la posición indicada. Capítulo 5: Colecciones. } void print() { System.size(). . for(int i = 0. // Dog is detected only at run-time } } .elementAt(). i < 7.addElement(new Dog(7)). class Cat { private int catNumber. } } public class CatsAndDogs { public static void main(String[] args) { Vector cats = new Vector(). i++) ((Cat)cats.out. 1998 // Source code file from the book "Thinking in Java" // Simple collection example (Vector) import java.

print("Pillada one!"). System.*.println( "Ardilla number " + ArdillaNumber). } } class VectorArdilla { private Vector v = new Vector(). public void addElement(Ardilla m) { v. i++) TrampaArdilla.addElement(new Ardilla(i)). } public int size() { return v. for(int i = 0. i++) Ardillas.: //: VectorArdilla.elementAt(i)). } } class TrampaArdilla { static void pilladaYa(Ardilla g) { g.size().pilladaYa(Ardillas. ni a los genéricos de Ada. Java no tiene clases parametrizadas * En Java no existe nada parecido a los templates de C++. .println(msg).size().addElement(m). class Ardilla { private int ArdillaNumber.java // Copyright (c) Bruce Eckel. Ej. Cursos de Verano de Málaga . } public static void main(String[] args) { VectorArdilla Ardillas = new VectorArdilla(). En Java 5 aparecen las clases genéricas. i < 3. } void print(String msg) { if(msg != null) System. for(int i = 0.util. * Si se quiere una colección de algo concreto.Programación en Java. } public Ardilla elementAt(int index) { return (Ardilla)v. 1998 // Source code file from the book "Thinking in Java" // A type-conscious Vector import java.elementAt(index). hay que construirlo explícitamente. i < Ardillas.out. Ardilla(int i) { ArdillaNumber = i.2005 -3- Hasta JDK 5.out. } } S G R Capítulo 5: Colecciones.

* Un Enumeration es un objeto que nos permite movernos por una colección como si de una secuencia cualquiera se tratase y. uniformizando el acceso. y luego decidimos. y que en la versión 1. y haciéndolo independiente de la colección concreta de que se trate. . hay que cerciorarse de que quedan más objetos en la secuencia. . que en Java se llaman Enumeration. * ¿Qué ocurre si empezamos nuestro proyecto utilizando Vectores. que devuelve el siguiente objeto almacenado en la secuencia. Cursos de Verano de Málaga .Programación en Java.Antes de recuperar un nuevo elemento.2 se llaman Iterator. . Para ello.2005 -4- Enumerators * Cada colección tiene una interfaz distinta. cualquier colección admite el método elements(). Para ello se usa hasMoreElements(). que devuelve un Enumeration. * Las operaciones principales que se permite hacer con un Enumeration son: . * Para evitar esto.Preparar a la colección para ser recorrida.Recorrer los elementos del iterador. Para ello. Capítulo 5: Colecciones. por cuestiones de eficiencia. los iteradores admiten el método nextElement(). surgen los iteradores. por tanto. utilizar Listas? Tendremos que modificar de cabo a rabo nuestro proyecto.

print().hasMoreElements()) ((Cat2)e. i++) cats.*.java // Copyright (c) Bruce Eckel. Enumeration e = cats. // Dog is detected only at run-time } } S G R Capítulo 5: Colecciones.println("Dog number " +dogNumber).elements().util.addElement(new Dog2(7)). } void print() { System.println("Cat number " +catNumber).2005 -5- Enumerators //: CatsAndDogs2. class Cat2 { private int catNumber. 1998 // Source code file from the book "Thinking in Java" // Simple collection with Enumeration import java.out. Dog2(int i) { dogNumber = i.addElement(new Cat2(i)).nextElement()). . Cursos de Verano de Málaga . } } class Dog2 { private int dogNumber. i < 7. while(e. Cat2(int i) { catNumber = i. } } public class CatsAndDogs2 { public static void main(String[] args) { Vector cats = new Vector(). } void print() { System. for(int i = 0. // Not a problem to add a dog to cats: cats.Programación en Java.out.

.remove(clave). Cursos de Verano de Málaga . .get(clave).size(). . Produce un Enumeration con todas las claves. Inserta un par en la tabla.keys(). Capítulo 5: Colecciones. dato). hay que sobrecargar ambos métodos. dato).2005 -6- Hashtables * Una tabla hash permite establecer una colección de pares (clave. Por defecto devuelve la dirección de memoria en que se encuentra el objeto. Indica cuantos pares hay en la tabla. * La interfaz básica es la siguiente: .Programación en Java.elements(). * La clase Object tiene un método hashCode() que. Elimina el par que posee la clave indicada. donde tanto la clave como el dato son objetos). devuelve un código único de tipo int. para cada objeto. . Devuelve el dato asociado a la clave buscada. . * Cuando se producen conflictos en la tabla hash. . la librería llama a equals() para comparar los objetos * Para usar un objeto como clave en una tabla hash. Produce un Enumeration con todos los datos asociados.put(clave.

i < 10. // you must override hashCode() and equals().util.Programación en Java. .out. Groundhog2(int n) { ghNumber = n.out.java // Copyright (c) Bruce Eckel.println((Prediction)ht. } public boolean equals(Object o) { return (o != null) && (o instanceof Groundhog2) && (ghNumber == ((Groundhog2)o). } public int hashCode() { return ghNumber. } } public class SpringDetector2 { public static void main(String[] args) { Hashtable ht = new Hashtable().ghNumber).containsKey(gh)) System. Cursos de Verano de Málaga .2005 -7- Hashtables //: SpringDetector2. Groundhog2 gh = new Groundhog2(3). class Groundhog2 { int ghNumber. for(int i = 0.out.get(gh)).put(new Groundhog2(i). } } S G R Capítulo 5: Colecciones. import java. System.println("ht = " + ht + "\n"). i++) ht.*. 1998 // Source code file from the book "Thinking in Java" // If you create a class that's used as a key in a Hashtable. System.println( "Looking up prediction for groundhog #3:").new Prediction()). if(ht.

for(int i = 0.print(v.toString()).out.put(new Integer(i). i < 5.out. Hashtable h = new Hashtable().elements()). System. PrintData.Programación en Java.println("Hashtable").elements()).java // Copyright (c) Bruce Eckel.println("Vector").*.2005 -8- Enumerators * Ahora que conocemos más colecciones (Vector y tabla hash).addElement(new Mouse(i)). i < 5. new Hamster(i)).util.out. PrintData. } } Capítulo 5: Colecciones. } } class Enumerators2 { public static void main(String[] args) { Vector v = new Vector(). 1998 // Source code file from the book "Thinking in Java" // Revisiting Enumerations import java. class PrintData { static void print(Enumeration e) { while(e. System. for(int i = 0.hasMoreElements()) System. i++) v. Cursos de Verano de Málaga .println( e. i++) h.print(h. queda más patente la utilidad homogeneizadora de la clase Enumerator. .nextElement(). //: Enumerators2.

* Todas las colecciones pueden producir un Iterator.Collection.2 S G * Java versión 1. . a través del método iterator(). . excepto porque: . Colección de objetos simples. next() en vez de nextElement(). etc. * Las clases punteadas son clases abstractas.Programación en Java.Map. * Las clases rayadas son interfaces. . * Las líneas con flecha indican implements. Capítulo 5: Colecciones.Utiliza nombres de métodos más simples: hasNext() en vez de hasMoreElements().2005 -9- Colecciones y Java 1. Colección de pares de objetos. que elimina el último elemento producido. agrupadas en losR conceptos de: .Incluye el método remove().2 incorpora toda una nueva batería de colecciones. que es lo mismo que un Enumeration. Puede llamarse a remove() por cada next() que se haga. Cursos de Verano de Málaga .

test(a). } } }.out. new Tester("iteration".hasNext()) { it. System. i < size * 10.println(": " + (t2 .class generados por javac.length. 5000) { void test(List a) { ListIterator it = a.util. for(int i = 0. j < a.currentTimeMillis(). it.name = name. i < tests.getName()). } } public static void main(String[] args) { test(new ArrayList()).size. 1998 // Source code file from the book "Thinking in Java" // Demonstrates performance differences in Lists import java.size = size. while(it.java // Copyright (c) Bruce Eckel. } abstract void test(List a).getClass().add(Integer. System. i++) { Iterator it = a. for(int i = 0.print(tests[i]. Capítulo 5: Colecciones.2005 -10- Test de List //: ListPerformance. test(new LinkedList()). i < REPS. ListIterator it = a. 300) { void test(List a) { for(int i = 0. long t1 = System.*.size(). // Test quantity Tester(String name. int size.t1)). } } }. i++) it. tests[i]. while(it. public static void test(List a) { // A trick to print out the class name: System.listIterator(3). long t2 = System. private abstract static class Tester { String name. . public class ListPerformance { private static final int REPS = 100.next(). } private static Tester[] tests = { new Tester("get". int size) { this. String s = "test". j++) a.iterator(). i++) { for(int j = 0.remove().println("Testing " + a.toString(i)). new Tester("insert".name). } } * Observar los . i < REPS.hasNext()) it.get(j).size()/2. 1000) { void test(List a) { int half = a.Programación en Java. this. } } }. }. Cursos de Verano de Málaga .listIterator(half). j++) a.currentTimeMillis().next().add(s). } }.out. 300) { void test(List a) { for(int i = 0. j < tests[i]. i++) { for(int j = 0.out. new Tester("remove".

iterator(). // 1º myIntList. que son clases que trabajan con un tipo indeterminado especificado en el momento de instanciar la clase genérica. // 3º p Así aparecen las colecciones genéricas.2005 -1- Capítulo 5.5 Clases genéricas y enumerados p JDK 1. una clase genérica produce un único fichero . tanto si se no se instancia como si se instancia varias veces con tipos reales diferentes.class.: p Así se mejora la legibilidad y la robustez.next(). Capítulo 5. //2º R Integer x = myIntList.5: Clases genéricas .Programación en Java. S G List<Integer> myIntList = new LinkedList<Integer>(). Cursos de Verano de Málaga . Ej.5 permite usar clases genéricas. p A diferencia de C++. ya que las violaciones de tipos se detectan en tiempo de compilación.add(new Integer(0)). en las que se indica que sólo pueden guardar un tipo de datos concreto.

incluso para instanciar otros tipos. Cursos de Verano de Málaga . Ej. Iterator<E> iterator(). el tipo formal de un genérico suele venir dado por una única letra mayúscula.: public interface List<E> { void add(E x). Ej. El tipo instanciado se puede usar dentro de manera normal.Programación en Java.: new List<Integer>() sustituye todas las E por Integer. } public interface Iterator<E> { E next(). boolean hasNext(). * La instanciación puede verse como una sustitución del tipo formal por un tipo real. } * Por convención. * Una clase genérica se crea indicando tras el nombre el/los tipo/s a instanciar.5: Clases genéricas . Capítulo 5.2005 -2- Crear genéricos simples p El programador también puede crear sus propias clases genéricas.

entonces X<B> no es subclase de X<A>. y ambas son genéricas entonces Y<C> es subclase de X<C>. porque permitiría hacer cosas como: lo.get(0). Capítulo 5. //1º List<Object> lo = ls.add(new Object()). * Si B es subclase de A. y X es genérica. * Si Y es subclase de X.2005 -3- Genéricos y subtipos * ¿El siguiente trozo de código es válido? List<String> ls = new ArrayList<String>(). // 3º String s = ls. Cursos de Verano de Málaga . S G R * Por tanto.5: Clases genéricas .Programación en Java. la línea 2ª produce un error en compilación. pero la segunda no. // 4º donde la tercera sentencia estaría metiendo un Object cualquiera en una lista declarada como sólo de String. //2º * La primera sentencia sí.

iterator().println(i.2005 -4- Supertipo base * Visto lo anterior.Programación en Java. * El carácter ? también se llama comodín. // Error en compilación ya que c es una colección de no se sabe qué. Cursos de Verano de Málaga . Capítulo 5.size(). k < c.add(new Object()).next()). pero no con un Collection<Integer> ni con nada que no sea de Objects. for (k = 0. una función como: void printCollection(Collection<Object> c) { Iterator i = c.5: Clases genéricas . pero no: c. k++) { System. * Si Collection<Object> no es el supertipo de todas las colecciones. }} sólo puede ser invocada con un Collection<Object> como parámetro. ¿quién es?: Collection<?> * La ? significa desconocido. por lo que se pueden hacer cosas como: Collection<?> c = new ArrayList<String>().out.

for (k = 0.size(). * Este for tampoco es útil si se quieren recorrer varias colecciones simultáneamente. k++) { System. }} también puede escribirse como: void printCollection(Collection<?> c) { for (Object e : c) { System.5: Clases genéricas .next()).out. como borrados. Cursos de Verano de Málaga . k < c. En otras palabras. Capítulo 5. cambio de valores. este for es útil si no es necesario acceder directamente al iterador.println(e). }} S G * Este tipo de bucle for sólo tiene sentido si no R se quieren realizar operaciones adicionales sobre la colección.println(i.iterator().2005 -5- Recorrido de colecciones * La función: void printCollection(Collection<Object> c) { Iterator i = c.Programación en Java.out. etc.

* Recordemos que algo como lo siguiente da error: public void addRect(List<? extends Figura> f) { f.} * Tampoco hay inconveniente en crear colecciones de colecciones.Programación en Java.: addRegistry(Map<String. Cursos de Verano de Málaga .5: Clases genéricas .add(0. Ej. } puesto que la ? Mantiene su significado de «desconocido». // Error en comp.. La declaración quiere decir: «una lista de algo desconocido que es Figura o hereda de Figura». ? extends Person> registry) { .. new Rectangulo()).2005 -6- Comodines acotados * La declaración List<? extends Figura> es un ejemplo de uso de comodín acotado. Ej.: new Vector<Stack<Integer>> Capítulo 5. * No hay ningún problema en declarar una clase genérica con varios tipos formales.

: static <T> void fromArrayToCollection( T[] a. fromArrayToCollection(oa. ej.5: Clases genéricas ..Programación en Java. Cursos de Verano de Málaga . entonces no debe usarse genericidad en un método.: public static <T> void copy( List<T> dest. // correct }} pero para invocarlo no se usa una instanciación explícita. co). sino implícita. * Los métodos genéricos permiten expresar entre los tipos de sus argumentos/resultado. Ej.: S G R pueden acotarse * Los tipos formales también con extends. Capítulo 5. Collection<Object> co = new ArrayList<Object>(). Ej.add(o). // Automáticamente se infiere que T es Object Si no hay tal dependencia. Collection<T> c) { for (T o : a) { c. List<? extends T> src){.2005 -7- Métodos genéricos * Un método también puede ser genérico..} Object[] oa = new Object[100].

Hundir<? super T> hnd){.2005 -8- Más sobre comodines * El uso de comodines es más claro y conciso que usar tipos formales.. Ej. Cursos de Verano de Málaga .addLast(figuras). Capítulo 5.Programación en Java. for (Figura f: figuras) { f. * La expresión ? super T quiere decir «algo desconocido que es supertipo de T».} Hundir<Object> h.: public static <T> T escribirTodo( Collection<T> col.: static List<List<? extends Figura>> historial = new ArrayList<List<? extends Figura>>(). Ej. public void dibujaTodo(List<? extends Figura> figuras) { historial.draw(this). // ¡Bien! * Usualmente. entonces el usar <? extends T> aumentará la flexibilidad. h). La relación supertipo es reflexiva. }} * T sólo se usa como tipo genérico cuando no hay nada específico que pueda distinguir al tipo real (lo que suele suceder en los métodos genéricos). Collection<String> cs. si los métodos de una API muy general sólo usan el tipo formal en los argumentos. String str = escribirTodo(cs. la clase Comparable o el método equals).5: Clases genéricas . el usar <? super T> será beneficioso (ej. Si la API sólo usa T para retornar cosas..

S G R * Casi puede pensarse que una Collection tradicional equivale a Collection<?>. Por ejemplo. *A pesar de ello.. ya que el compilador no tiene forma de asegurar que la colección que devuelve la función getPartes() es una Collection<Partes>. * Por tanto un raw type es parecido a un tipo comodín.5: Clases genéricas .. c. pero no es totalmente cierto ya que la sentencia marcada en rojo sí funciona.Programación en Java.} } public interface Pieza { Collection getPartes().2005 -9- Colecciones tradicionales * Las colecciones tradicionales se llaman ahora raw types. Collection partes) {. pero no se puede chequear en tiempo de compilación.. Inventario.} public static Pieza getPieza(String nombre) {. ¡Mucho cuidado con los unchecked warnings. Capítulo 5.getPartes(). dadas unas funciones como: public interface Parte { .. } no hay problema en realizar una invocación como: Collection<Parte> c = new ArrayList<Parte>().getPieza(”Cosa”).add(new Cuchilla()). c). } public class Inventario { public static void añadirPieza(String nombre.añadirPieza(”Cosa”.add(new Guillotina()) . Cursos de Verano de Málaga . dicha sentencia emite un «unchecked warning» en tiempo de compilación... Collection<Parte> k = Inventory. * Los raw types se pueden mezclar con las genéricas. c.

* Por tanto. * Ello se debe a que todas las clases instanciadas comparten el mismo fichero .} // Error en comp.5: Clases genéricas . Es errónea pues no existe un . por lo que no tiene sentido utilizarlo en operaciones que implican al tiempo de ejecución. Cursos de Verano de Málaga .class para todas las clases instanciadas * Puede resultar sorprendente que el siguiente código: List <String> l1 = new ArrayList<String>(). Capítulo 5.getClass() == l2. Esto hace que los tipos formales no se puedan utilizar en las funciones y/o variables estáticas declaradas en una clase genérica.. un tipo real sólo se utiliza en tiempo de compilación.getClass()). <T> T badCast(T t. List<Integer> l2 = new ArrayList<Integer>().println(l1.Programación en Java. * Como consecuencia de esto.2005 -10- Un . Object o) {return (T) o. mientras que las sentencias: Collection<String> cstr = (Collection<String>) cs.. De hecho. los elementos estáticos son compartidos por todas las clases instanciadas.class.} producen las dos un unchecked warning ya que no es algo que el compilador pueda asegurarnos que va a funcionar en ejecución. devuelva el valor true. lo que hace a una clase genérica es que tiene el mismo comportamiento sean cuales sean sus tipos reales. La sentencia: if (cs instanceof Collection<String>) { .out. System.class de Collection<String>.

& * Puede usarse acotación múltiplede 1 2 Tn como por ejemplo: public static <T extends Object & Comparable<? super T>> T max(Collection<T> coll) para lo cual se utiliza el símbolo &. xs.add(x). el tipo real que se utiliza en la erasure es el primero de la lista.Programación en Java.iterator().. a pesar de las unchecked warnings. la integridad de la máquina virtual de Java G nunca se pone en peligro. Cursos de Verano de Málaga . Capítulo 5. R la forma: T & T & . } al ejecutarlo se producirá un fallo. List xs = ys. * Cuando se utiliza acotación múltiple.next().. * El motivo de esto es que el compilador de Java implementa los genéricos mediante una conversión front-end denominada erasure.5: Clases genéricas . S * En cualquier caso. // unchecked warning return ys.2005 -11- Erasure y herencia múltiple * Si se escribe el siguiente código: public String loophole(Integer x) { List<String> ys = new LinkedList<String>().

ej.: ESTACION_VERANO .Programación en Java. public static final int VERANO= 1. public static final int INVIERNO = 3. * En JDK 5.: for(Estación e : Estación.Dado que se trata de constantes manejadas en tiempo de compilación. Cursos de Verano de Málaga .Dado que son int no tiene sentido visualizarlas con toString(). OTOÑO. INVIERNO } * Además.2005 -12- Enumerados * En versiones anteriores al JDK 5. public static final int OTOÑO= 2. La función toString() visualiza correctamente el identificador y pueden recorrerse con el for de los arrays.values()) System. un enum es una clase en toda regla que implementa Comparable y Serializable.5: Clases genéricas . ej. la declaración anterior puede sustituirse por una clase nueva. .println(e). .Las constantes deberían tener un prefijo para evitar colisiones con otras constantes. todos los clientes se deben recompilar si se añade una nueva constante en medio y se renumeran las ya existentes. los enumerados se declaraban como variables estáticas finales: public static final int PRIMAVERA= 0. VERANO.out. Capítulo 5.Una estación es un int lo cual no tiene sentido. tal como: enum Estación { PRIMAVERA. * Sin embargo esto tiene muchos problemas: .

0518e6). // en kilogramos private final double radio.4397e6). 6.137e6). 2.024e+26. Cursos de Verano de Málaga .1492e7).values() devuelve un array de objetos de tipo Estación.67300E-11.0268e7).4746e7).27e+22. MARTE (6.686e+25. private final double masa.37814e6). 7.masa = masa. JÚPITER (1. VENUS (4.5559e7).5: Clases genéricas . TIERRA (5.2005 -13- Constructor de enumerados * La invocación Estación. double radio) { this.9e+27. 3. // en metros Planeta(double masa.303e+23.Programación en Java. 2.976e+24.688e+26. } } S G R Capítulo 5. URANO (8. this.421e+23. SATURNO (5.radio = radio. * El siguiente ejemplo ilustra cómo es posible asignar información (masa y radio) a los enumerados: public enum Planeta { MERCURIO (3. 2. 1. } // Constante gravitacional universal (m 3 kg -1 s -2) public static final double G = 6.3972e6). } double pesoEnSuperficie(double otraMasa) { return otraMasa * gravedadEnSuperficie(). 6. 6.869e+24. double gravedadEnSuperficie() { return G * masa / (radio * radio). NEPTUNO (1. PLUTÓN (1.

2005 -14- Comportamiento diferenciado entre constantes * Cada constante de un enumerado puede tener un comportamiento diferente. } }. double y) { return x / y.parseDouble(args[1]). } }. op. MENOS { double eval(double x. } * Estos mecanismos de gestión de enumerados aumentan la claridad y eficiencia de los programas Java. y)).y. double y = Double. op. } de tal forma que puede ser invocada como: public static void main(String args[]) { double x = Double.printf( "%f %s %f = %f%n". for (Operation op : Operation. // Hace la operación aritmética representada por una cte. ENTRE { double eval(double x. y. double y) { return x . } }. Cursos de Verano de Málaga . double y) { return x + y. double y). x. Capítulo 5.5: Clases genéricas .Programación en Java. double y) { return x * y. POR { double eval(double x. abstract double eval(double x. } }.values()) System. de la forma: public enum Operacion { MAS { double eval(double x.out.parseDouble(args[0]).eval(x.

cten) // produce un subconjunto de enumerados. Datum>(Planeta.Programación en Java.MERCURIO.BOLD. * Ejemplo de uso: Set<Planeta> planetasInteriores = EnumSet.. cte2.of(Style. fin) // proporciona un rango de enumerados.class).of(cte1.range(Planeta. Planeta. S G R Capítulo 5.. Cursos de Verano de Málaga . STYLE.2005 -15- Clases de apoyo * La clase EnumSet proporciona operaciones para facilitar el trabajo con enumerados: EnumSet.ITALIC).: Map<Planeta. Style st = EnumSet. Ej. Datum> info = new EnumMap<Planeta. * La clase EnumMap es una implementación altamente eficiente de un mapa.range(inicio.5: Clases genéricas . EnumSet.MARTE).. .

. Si esta zona especial no existe. * Java incorpora palabras reservadas para trabajar con errores y excepciones. Capítulo 6: Tratamiento de excepciones. etc. el método actual se cancela y se vuelve al método llamante. * Todos los fallos posibles en ejecución heredan de Throwable.2005 -1- Capítulo 6 Tratamiento de excepciones * El tratamiento de errores en lenguajes como C o Modula-2 supone una auténtica pesadilla. * Hay excepciones que «vienen de fábrica». Cuando se produce una excepción. punteros nulos. Cursos de Verano de Málaga . Hay distintos tipos de objetos para identificar distintos tipos de excepciones. S G * Cuando se produce un fallo que impide continuar la ejecución se «eleva» una excepción. buscando en éste la susodicha zona de código especial. en la que hay que testear constantemente en switches externos a la lógica del programa. Java suministra dos subclases fundamentales que derivan de Throwable: . .Exception: Son los fallos típicos de los programas: división por cero. el flujo de ejecución salta automáticamente a una zona especial del código.Programación en Java. el programador puede crear las suyas propias. * Una excepción se considera un objeto que lleva asociada información sobre el fallo ocurrido. Para ello se emplea la palabra R reservada throw. Así sucesivamente hasta que la excepción sea tratada. pero además. etc.Error: Reservado para fallos internos del sistema: falta de memoria.

puede tener distintos constructores. Cursos de Verano de Málaga . puede contener toda la información que se quiera.. } catch (TipoException1 t1) { // Controlador de excepciones del tipo 1 } catch (TipoException1 t2) { // Controlador de excepciones del tipo 2 } .: if (t == null) throw new NullPointerException("t = null").2005 -2- «Elevar» y «atrapar» una excepción * Cuando se «eleva» o se «lanza» una excepción.. } Capítulo 6: Tratamiento de excepciones. * Cuando se eleva una excepción.Programación en Java. lo primero que hay que hacer es crear el objeto excepción. Ej. . Una región protegida tiene el formato: try { // Código que puede generar excepciones.. con new. * Dado que una excepción es un objeto más. etc. se supone que ésta va a ser atrapada en algún lugar del código. } catch (TipoException1 tn) { // Controlador de excepciones del tipo n } finally { // Trozo de código que se ejecutará siempre. Para ello se emplea el concepto de «región protegida».

2005 -3- Captura y «relanzamiento».getMessage(). divZero { . . Cuando en el try se eleva una excepción. Cuando un bloque catch eleva una excepción.Constructor que admite un String: descripción del problema. .} * Para capturar excepciones también se emplea el concepto de herencia. De esta forma es posible capturar cualquier tipo de excepción mediante un catch que captura un objeto de tipo Exception. Este bloque tiene sentido para cuando hay que cerrar ficheros que se han abierto en la región protegida. * Exception posee: . se busca el primer catch que tenga como argumento una excepción del tipo elevado. Convierte la excepción en una cadena. Visualiza la pila de llamadas a métodos. S G R * El trozo de código situado en la parte finally se ejecutará siempre.. del que heredan todos los demás. Se indica que un método puede acabar de forma anómala. mediante la palabra throws en la cabecera: void f() throws tooBig. Cursos de Verano de Málaga . o cosas parecidas. puede volver a elevarla. tanto se haya producido alguna excepción como si no. * Es posible que el bloque catch no sea capaz de gestionar la excepción.. en ese momento se ejecutará su cuerpo.Programación en Java.printStackTrace(). el método en el que se encuentra finaliza de forma anómala. En tal caso. . Capítulo 6: Tratamiento de excepciones. .. Palabra reservada finally * Los catch establecen una especie de switch para atrapar las excepciones elevadas en el bloque try.toString(). tooSmall. Toma el String dado en el constructor. y la excepción se da por gestionada.

out.getMessage()). } try { g(). throw new MyException().out.toString(): " + e.java Copyright (c) Bruce Eckel. System. } catch(Exception e) { System.getMessage(): " + e. } catch(MyException e) { e. Cursos de Verano de Málaga .println( "Throwing MyException from f()"). System. } catch(MyException e) { e.printStackTrace():").java // Copyright (c) Bruce Eckel. .println("e.toString()).println("e.printStackTrace(). public class ExceptionMethods { public static void main(String[] args) { try { throw new Exception("Here's my Exception").printStackTrace().printStackTrace().println("e.out. 1998 // Source code file from the book "Thinking in Java" // Demonstrating the Exception Methods package c09.2005 -4- Ejemplo * Ejemplo de bloque o región protegida. //: Inheriting.Programación en Java. } } } Capítulo 6: Tratamiento de excepciones. } public static void main(String[] args) { try { f(). throw new MyException("Originated in g()"). //: ExceptionMethods. e. } public static void g() throws MyException { System. 1998 // Source code file from the book "Thinking in Java" // Inheriting your own exceptions class MyException extends Exception { public MyException() {} public MyException(String msg) { super(msg).println( "Throwing MyException from g()").out. } } } * Ejemplo de creación de excepciones propias.println("Caught Exception").out. } } public class Inheriting { public static void f() throws MyException { System.out. System.

* finally se ejecuta aunque la excepción no sea capturada. 1998 // Source code file from the book "Thinking in Java" // How an exception can be lost class VeryImportantException extends Exception { public String toString() { return "A very important exception!". toda función puede lanzar RuntimeException. } } } S G R Capítulo 6: Tratamiento de excepciones.java // Copyright (c) Bruce Eckel.Programación en Java. * Hay que tener cuidado con la pérdida de excepciones. } public static void main(String[] args) throws Exception { LostMessage lm = new LostMessage(). } } public class LostMessage { void f() throws VeryImportantException { throw new VeryImportantException(). } void dispose() throws HoHumException { throw new HoHumException(). } finally { lm. try { lm. } } class HoHumException extends Exception { public String toString() { return "A trivial exception".f(). //: LostMessage.dispose(). * Es posible construir una excepción que no posea código alguno: class ExcepcionSimple extends Exception { } * Cuando se reescribe un método sólo se pueden lanzar las excepciones que se describían en el método base. y sin necesidad de especificarlo. .2005 -5- Detalles sobre excepciones * De forma implícita. Cursos de Verano de Málaga .

S G * Todas las clases que implementan canales en los que se puede escribir heredan de OutputStream.2005 -1- Capítulo 7 E/S con Java * Dado que la entrada/salida depende de la platafroma en que Java se ejecute.Otro stream. el lenguaje Java no posee operaciones de E/S. .Un String. . Cursos de Verano de Málaga . .Una conexión con Internet.Un array de bytes.Una secuencia de streams.Programación en Java. En su lugar posee una compleja librería. Capítulo 7: E/S con Java. .Un fichero en disco. y todas aquellas de las que R se puede leer heredan de InputStream. Las fuentes pueden ser: . * InputStream agrupa a todas las clases que representan canales de los que se puede leer. . Por cada tipo de fuente de datos se tiene una subclase de InputStream. éste no tiene nada ver con su homónimo de C++. * Aunque se utiliza el concepto de canal (stream). .

DataInputStream: Prepara al canal de entrada para recoger valores primitivos (int.).ByteArrayInputStream: La entrada es un buffer de memoria. .Programación en Java. . Crea un buffer interno.StringBufferInputStream: El fuente es un String. . Capítulo 7: E/S con Java. long.SequenceInputStream: Convierte una secuencia de InputStream en uno solo. .FilterInputStream: De aquí heredan todos los estratos.LineNumberInputStream: Lleva la cuenta del número de líneas que han sido leídas. .BufferedInputStream: Evita que en cada operación de lectura se efectúe una lectura física. * Java suministra una serie de clases que proporcionan distintas funcionalidades a los canales de entrada y de salida. Cursos de Verano de Málaga . . .ej. . .PipedInputStream: La entrada es un pipeline de salida.PushbackInputStream: Permite reinsertar caracteres leídos en el canal de entrada. char.FileInputstream: El fuente es un fichero. P.2005 -2- Estratificación * Para cada una de las fuentes anteriores se tienen las siguientes subclases: .: . Se pueden colocar en capas para suministrar más de una funcionalidad a la vez: es la estratificación. etc.

Cursos de Verano de Málaga . while((s = in. } catch(IOException e) { System. s2 = new String(). } S Gdel disco. y a continuación lo prepara para leer datos primitivos en formato estándar.close(). in.out.Programación en Java. * Por último cierra el fichero. R * A continuación lee su contenido línea por línea. establece un buffer * Este ejemplo abre un fichero para él.println( "File Not Found:" + args[0]).2005 -3- Ejemplo: fichero entrada con buffer try { // 1. es necesario agrupar todo el proceso en una región protegida.out. Buffered input file DataInputStream in = new DataInputStream( new BufferedInputStream( new FileInputStream(new String("MiFichero. . y que pueden producirse excepciones de E/S. * Dado que el fichero que se abre puede no existir.txt")))). } catch(FileNotFoundException e) { System. String s. en la que se capturen dichas excepciones.println("IO Exception").readLine())!= null) s2 += s + "\n". y el fichero entero lo inserta en un objeto de tipo String. Capítulo 7: E/S con Java.

Cursos de Verano de Málaga . } catch(IOException e) { System.Programación en Java. luego no es necesario acoplarle ningún estrato más. int c.out. * La propia fuente establece un buffer.println("IO Exception").out.read()) != -1) System.2005 -4- Ejemplo: entrada desde una cadena try // 2. . * De nuevo controlamos los posibles errores de E/S que aparezcan. vamos leyendo carácter a carácter desde una cadena de caracteres. luego hay que convertirlo a char. Input from memory StringBufferInputStream in2 = new StringBufferInputStream(s2). Capítulo 7: E/S con Java. read() devuelve cada byte como un entero. while((c = in2.print((char)c). } * En este caso.

} S G R Capítulo 7: E/S con Java.println("IOException").out.readByte()).readByte()).out. Formatted memory input try { DataInputStream in3 = new DataInputStream( new StringBufferInputStream(s2)). Aquí no se ha detectado. // 3.2005 -5- Ejemplo: cadena entrada con buffer // 3. Cursos de Verano de Málaga .println("IO Exception").print((char)in3.out.Programación en Java.println("End of stream encountered"). } } catch(IOException e) { System. sino que se ha delegado en capturar la excepción IOException. aunque en este caso. while(in. incluso el <EOF> se considera un carácter válido. } * A la lectura desde una cadena se le ha añadido la posibilidad de leer datos primitivos. luego no hay forma de detectar el final del fichero. } catch (IOException e) { System. } catch(EOFException e) { System. Formatted memory input try { DataInputStream in = new DataInputStream( new BufferedInputStream( new FileInputStream("TestEof. la lectura se ha efectuado igualmente en base a bytes posteriormente convertidos a caracteres. Un método mejor es emplear available() que devuelve el número de bytes que quedan por leer.available() != 0) System. while(true) System.print((char)in.err.out. . * Con este método.java"))).

* Es especialmente interesante la conversión a int. " + "un entero.out."). otro carácter y un float.readLine(). un carácter.in.io. char c2 = (char)(d. cuyo nombre es System.*.out. consecuencia de las teclas pulsadas.getClass().2005 -6- Ejemplo: la entrada estándar import java. Capítulo 7: E/S con Java.Programación en Java.println(System.println("Indale.readLine())). float f = (new Float(d. } } * Este ejemplo ilustra como insertar cosas desde la entrada estándar. Cursos de Verano de Málaga . Sin embargo todas las entradas desde el teclado son secuencias de caracteres.readLine().readByte()). * System. (para lo cualno hay ningún problema) y convertirla al formato que convenga.println("Inserta una cadena. DataInputStream d = new DataInputStream(System.println(s + "\n" + i + "\n" + c + "\n" + c2 + "\n" + f + "\n"). * Para leer correctamente es necesario leer una tira de caracteres. System.out.readLine(). public class Prueba { public static void main(String[] args) { try { System.charAt(0). La entrada estándar queda representada por un objeto de tipo BufferedInputStream.in). y el método que permite convertir a cualquier otro tipo (excepto char). hay un error. }. 10). String s = d.floatValue().").out. . } catch (IOException e) { System. char c = d. System.in. int i = Integer.in permite leer sólo entrada binaria y caracteres.parseInt(d.getName()).

Un array de bytes.Un fichero en disco.).ByteArrayOutputStream: Escribe en un buffer de memoria. .Programación en Java. long.FileOutputStream: Escribe en un fichero. R . . Por cada tipo de destino de datos se tiene una subclase de OutputStream.FilterOutputStream: De aquí heredan todos los estratos de salida. . etc. . Cursos de Verano de Málaga . . char. Capítulo 7: E/S con Java.PipedOutputStream: Enlaza con un PipedInputStream. y PrintStream se encarga de la visualización. .PrintStream : Para producir salida inteligible.DataOutputStream: Prepara al canal de salida para recoger valores primitivos (int.BufferedOutputStream: Para que todas las operaciones utilicen un buffer de memoria.2005 -7- Salida de datos * OutputStream agrupa a todas las clases que representan canales en los que se puede escribir. .Otro stream. Los destinos pueden ser: . DataOutputStream se encarga del almacenamiento. S G * Para ello se tienen las siguientes subclases: . * FilterOutputStream suministra los siguientes estratos: .

PrintStream out1 = new PrintStream( new BufferedOutputStream( new FileOutputStream( "IODemo.readLine()) != null ) out1.println( "End of stream encountered").out es de tipo texto. } * Este ejemplo hace uso de LineNumberInputStream.close(). . DataInputStream in4 = new DataInputStream(li). De esta forma. * El número de línea se obtiene con getLineNumber(). que se modifica para que tenga un buffer. Line numbering & file output try { LineNumberInputStream li = new LineNumberInputStream( new StringBufferInputStream(s2)).out"))). lo que hace que lo que se va escribiendo lo haga en formato textual.out.out». Para sacar el número de línea que se está leyendo. Cursos de Verano de Málaga .println( "Line " + li. * En este caso. En otro caso sería binario.Programación en Java. out1. y luego se convierte en PrintStream. lo que se consigue construyendo el DataInputStream en dos pasos.2005 -8- Ejemplo escritura en fichero de texto // 4. // finalize() not reliable! } catch(EOFException e) { System. es necesario tener un manejador a un objeto de este tipo. while((s = in4. el fichero IODemo. lo que se lee por un lado se escribe en un fichero «IODemo. Capítulo 7: E/S con Java.getLineNumber() + s).

y DataInputStream para recuperarlos.Programación en Java. Cursos de Verano de Málaga .out. Storing & recovering data try { DataOutputStream out2 = new DataOutputStream( new BufferedOutputStream( new FileOutputStream("Data.out. .println( "End of stream encountered").txt"))).println(in5. y en qué orden. cuando se lee del fichero. Capítulo 7: E/S con Java.2005 -9- Ejemplo: guardar y recuperar datos // 5.14159). System. * Para que todo esto funcione bien. } catch(EOFException e) { System. out2. out2. out2.writeBytes( "Here's the value of pi: \n"). } S G R * Aquí se utiliza un DataOutputStream para guardar datos en formato binario.txt"))).out. System.println(in5.close().writeDouble(3. hay que saber exactamente qué tipos de datos se han guardado.readLine()).readDouble()). DataInputStream in5 = new DataInputStream( new BufferedInputStream( new FileInputStream("Data.

// Aquí vienen los catch. rf = new RandomAccessFile("rtest. i++) System. Cursos de Verano de Málaga . Capítulo 7: E/S con Java.getFilePointer(). Para saber el tamaño del fichero.writeDouble(i*1. . o en lectura/escritura "rw". Reading/writing random access files RandomAccessFile rf = new RandomAccessFile("rtest. "rw").seek(5*8). mediante seek().dat".out.414).writeDouble(47. junto con los siguientes métodos fundamentales: .close(). motivo por el cual puede ser necesario saber la longitud de los distintos tipos de datos que se guardan. rf. "r"). rf. El punto se especifica en bytes. .close().dat". for(int i = 0. i < 10.seek().Programación en Java.. i < 10.0001). rf = new RandomAccessFile("rtest. "rw"). try { // 6. rf.dat".println( "Value " + i + ": " + rf. rf.readDouble()). i++) rf. . Para irse a un punto concreto del fichero. rf. Para saber en qué posición del fichero nos encontramos.close(). for(int i = 0... y posicionarse en cualquiera de ellos directamente. * RandomAccessFile viene a ser una mezcla entre DataInputStream y DataOutputStream.Los constructores necesitan saber si el fichero se abre para sólo lectura "r".2005 -10- Ficheros de acceso directo * La clase RandomAccessFile se utiliza para acceder a ficheros compuestos de registros de tamaño conocido. para leerlo o modificarlo.length(). .

Programación en Java. for(int i = 0.indexOf(afn) != -1.println(list[i]). Admite el método list() que obtiene una lista con los nombres de los ficheros de dicho directorio. al que list() llama para cada uno de los nombres de fichero del directorio indicado. Capítulo 7: E/S con Java.*. * A list() se le puede pasar un parámetro que será un objeto que implementa la interfaz FilenameFilter. Si accept() devuelve true el fichero se admite. Cursos de Verano de Málaga .printStackTrace().length == 0) list = path.").length. public boolean accept(File dir. String name) { return name.list(). public class DirList { public static void main(final String[] args) { try { File path = new File(".2005 -11- La clase File * La clase File sirve para guardar nombres de ficheros y de directorios.io. // Displays directory listing import java. String[] list. .out. if(args. } } } S G R * Nótese que no se permite el uso de caracteres comodines. } catch(Exception e) { e. se rechaza en caso contrario. } } ). else list = path. i++) System. i < list.list(new FilenameFilter() { String afn = args[0]. Todo objeto del tipo FilenameFilter debe tener un método llamado accept().

out.ttype. System.TT_NUMBER: d = st.TT_EOF) { String s. } } } * En este ejemplo se utiliza una librería que posee Java para efectuar la partición de un texto de entrada en bloques: números y palabras fundamentalmente.util.out.nextToken() unsuccessful").TT_WORD: s = st.println("Una palabra: " + s). Capítulo 7: E/S con Java.*. // Already a String System.nval: Si el token es un número.sval: Si el token es una palabra.ordinaryChar('.println("Un carácter: " + s).sval. break.out. break.out.Programación en Java.nval. posee el valor de dicho número como double. break.ordinaryChar('-'). Cursos de Verano de Málaga . double d.println("Fin de linea"). contiene a dicha palabra. case StreamTokenizer.io. Indica el tipo del token actual: TT_EOL.2005 -12- StreamTokenizer import java.nextToken(). case StreamTokenizer. TT_EOF.valueOf((char)st. st. o un carácter si no es ninguno de ellos.*.println( "st.nextToken() != StreamTokenizer.in).'). System. * Es una alternativa para la lectura desde el teclado.ttype). . import java. public class Token { public static void main(String[] args) { S t re a m T o k e n i z e r s t = n e w StreamTokenizer(System. Carga el siguiente token. } } } catch(IOException e) { System.TT_EOL: System. * Posee los siguientes elementos: . .println("Un número: " + d). . st. TT_WORD. default: // single character in ttype s = String. TT_NUMBER. try { while(st. . switch(st.out.ttype) { case StreamTokenizer.

1 ha sustituído casi todas las clases que hemos visto por otras nuevas más eficientes. .2005 -13- E/S con Java 1. * Para la entrada son: Raíz principal: Antes: InputStream Descendientes directos: Antes: ByteArrayInputStream Ahora: Ahora: Reader CharArrayReader StringReader FileReader PipedReader SequenceInputStream FilterInputStream FilterReader Estratos que heredan directamente de Reader: S StringBufferInputStream FileInputStream G PipedInputStream SequenceInputStream R DataInputStream BufferedInputStream LineNumberInputStream PushBackInputStream Antes: Ahora: DataInputStream BufferedReader LineNumberReader PushBackReader (es el único que hereda de FilterReader) * Se puede convertir un InputStream en un Reader mediante el estrato InputStreamReader.1 Entrada * Java versión 1. Capítulo 7: E/S con Java.Programación en Java. Cursos de Verano de Málaga .

Programación en Java. * Se puede convertir un OutputStream en un Writer mediante el estrato OutputStreamWriter. que no existe StringWriter FileOutputStream FileWriter PipedOutputStream PipedWriter FilterOutputStream FilterWriter Estratos (ahora descienden directamente de Writer): Antes: BufferedInputStream PrintStream DataOutputStream Ahora: BufferedWriter PrintWriter DataOutputStream * El tratamiento sigue siendo igual que antes.2005 -14- E/S con Java 1. Capítulo 7: E/S con Java. Cursos de Verano de Málaga .1 Salida * Para la salida son: Raíz principal: Antes: OutputStream Descendientes directos: Antes: ByteArrayOutputStream Ahora: Ahora: Writer CharArrayWriter StringBufferOutputStream. .

BufferedReader in2 = new BufferedReader( new InputStreamReader( new GZIPInputStream( new FileInputStream("test. BufferedOutputStream out = new BufferedOutputStream( new GZIPOutputStream( new FileOutputStream("test.write(c).out. while((c = in.*.println(s). //: GZIPcompress.gz"))). 1998 // Source code file from the book "Thinking in Java" // Uses Java 1.zip. Capítulo 7: E/S con Java.util.read()) != -1) out.zip. System. } catch(Exception e) { e.java Copyright (c) Bruce Eckel.out. * La utilización es muy simple.out.println("Reading file"). public class GZIPcompress { public static void main(String[] args) { try { BufferedReader in = new BufferedReader( new FileReader(args[0])).2005 -15- Compresión * Java 1. out.close(). . S G R int c.readLine()) != null) System. String s.println("Writing file"). System. } } } * El proceso de lectura escritura es el mismo de siempre.gz")))). Cursos de Verano de Málaga . import java. in.1 posee clases que permiten trabajar con ficheros comprimidos.io. while((s = in2.*.Programación en Java.printStackTrace().util.close(). import java. Se encuentran en el paquete java.1 GZIP compression to compress a file. El sistema se encarga de todo.

No crea ninguna descripción automáticamente. sonidos.jar * Los ficheros . pueden incluirse directorios enteros. Sólo guarda los ficheros. Si no se pone. e indicarse dicho fichero explícitamente en la variable de entorno CLASSPATH.Programación en Java. * Formato: jar [opciones] destino [descripción] ficheros Opción c t x x fichero f m v O M Descripción Crea un fichero nuevo o vacío.3\jre\lib\ext. Extrae todos los ficheros. *Además los . Permiten insertar clases. y tratarlo como un único bloque a través de la red. Cursos de Verano de Málaga . imágenes.jar comprimen los ficheros que contiene.jar (Java Archive) son especialmente útiles cuando se trabaja con Internet. Modo verbose. Extrae el fichero indicado. debe usarse la opción O. * Si desea usarse en local un fichero . Lista el contenido del fichero.jar. No los comprime. Capítulo 7: E/S con Java. . * Como ficheros.2005 -16- Ficheros . en un sólo fichero. Necesario cuando se usan en local. disminuyendo así el tráfico por la red. en lugar de los ficheros indicados El fichero indicado contiene la descripción. etc. o bien colocarlo como extensión del entorno Java en el directorio jdk1. se usa la E/S estándar como fuente/destino.

y así sucesivamente. . * Cuando se recupera un objeto. la persistencia se hace vía Serialización. * En Java.Crear un objeto InputStream. tal que pueda ser posteriormente guardada y recuperada desde un fichero. * Para guardar un objeto es necesario que implemente la interfaz Serializable. .Ponerle un estrato del tipo ObjectOutputStream.Crear un objeto OutputStream. todos los componentes deben ser también serializables.Escribir los objetos mediante writeObject().Leer los objetos mediante readObject(). sino también todos los objetos que contiene.class a que corresponde cada objeto guardado. lo que devuelve un manejador a un Object. Cursos de Verano de Málaga . * Los pasos para guardar un objeto serializable son: . que consiste en convertir el objeto en una secuencia de bytes. el sistema Java debe ser capaz de encontrar el . Para conseguirlo. Capítulo 7: E/S con Java.Ponerle un estrato del tipo ObjectInputStream. * Lo interesante a la hora de guardar un objeto es que se guarden no sólo sus datos primitivos. S G * Los pasos para recuperarlo son: R .Programación en Java.2005 -17- Persistencia * La persistencia es el proceso que permite guardar cualquier objeto en disco para ser recuperado posteriormente. . que deberá ser convertido (downcasted) a su verdadero tipo. . .

private char c. if(next != null) s += next.writeObject(w). w2 = " + w2). new Data(r()). Probar el ejemplo. } public static void main(String[] args) { Worm w = new Worm(6. out. y probarlo de nuevo haciendo que Data no sea serializable. System. Cursos de Verano de Málaga .out. System. } } public class Worm implements Serializable { // Generate a random int value: private static int r() { return (int)(Math. } catch(Exception e) { e. } } } Capítulo 7: E/S con Java.out.println("Default constructor"). for(int i = 0.readObject(). Data(int x) { i = x. new Data(r()) }.toString().close(). String s = (String)in. } public String toString() { return Integer.out.printStackTrace(). out. c = x. } private Data[] d = { new Data(r()). // Value of i == number of segments Worm(int i.length.out")).random() * 10).Programación en Java.*.println(" Worm constructor: " + i). return s. out. Worm w2 = (Worm)in. s += ")". char x) { System. } public String toString() { String s = ":" + c + "(". . try { ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("worm.toString().println(s + ".readObject(). } Worm() { System.out.println("w = " + w).writeObject("Worm storage"). private Worm next. // Also flushes output ObjectInputStream in = new ObjectInputStream( new FileInputStream("worm.2005 -18- Ejemplo de serialización * En este ejemplo se guarda una objeto enorme formado a su vez por otros objetos. i++) s += d[i]. if(--i > 0) next = new Worm(i.toString(i). (char)(x + 1)).out")). i < d. class Data implements Serializable { private int i. 'a'). import java.io.

que son automáticamente llamados por el sistema durante el proceso de serialización o deserialización respectivamente. etc. a diferencia de cuando se implementa Serializable. * La interfaz Externalizable añade dos métodos que deben ser reescritos por el implementador: son writeExternal() y readExternal(). emplearemos los métodos propios de DataOutput: writeInt().2005 -19- La interfaz Externalizable * Para obtener un control total sobre qué elementos se guardan y cuáles no. Capítulo 7: E/S con Java. en el que hay que escribir los objetos componentes que se quieran mediante writeObject(). se llama a su constructor. antes de cargar un objeto.Programación en Java. y posteriormente se llama automáticamente a readExternal(). Si lo que se quiere guardar son primitivas. S G * En writeExternal() y readExternal() hay que leer y excribir R explícitamente todos los objetos y datos primitivos que se quiera. writeLong(). Cursos de Verano de Málaga . writeDouble(). * writeExternal() recibe como parámetro un objeto ObjectOutput (que hereda de DataOutput). . * En este caso. que extiende a la Serializable. se tiene la interfaz Externalizable.

*. // You must do this: s = (String)in. int a) { System. i = a.println("Blip3.out")).out. s = x. .println("Blip3. i not initialized } public Blip3(String x.readInt(). // No initialization public Blip3() { System.out.toString()). } } } * Las líneas marcadas indican los lugares donde se hacen las llamadas para serializar y deserializar objetos y componentes. 47).println("Constructing objects:").readExternal").out")). // s & i initialized only in non-default constructor.java // Copyright (c) Bruce Eckel. 1998 // Source code file from the book "Thinking in Java" // Reconstructing an externalizable object import java. int a)").out.*.Programación en Java.toString()).println("Blip3(String x. class Blip3 implements Externalizable { int i.readObject().out. Cursos de Verano de Málaga .out. } public static void main(String[] args) { System. // Now get it back: ObjectInputStream in = new ObjectInputStream( new FileInputStream("Blip3. System. System. } public void readExternal(ObjectInput in) throws IOException. System.println(b3.util. ClassNotFoundException { System. o. String s.println(b3.2005 -20- Ejemplo de Externalizable //: Blip3.writeInt(i). } public void writeExternal(ObjectOutput out) throws IOException { System. import java. try { ObjectOutputStream o = new ObjectOutputStream( new FileOutputStream("Blip3.readObject().writeObject(s).println("Blip3 Constructor").out. b3 = (Blip3)in.writeObject(b3).writeExternal"). System.close().printStackTrace(). i =in.out.println("Saving object:").out.out. o. Capítulo 7: E/S con Java. // You must do this: out.println("Recovering b3:"). } public String toString() { return s + i. out. } catch(Exception e) { e. Blip3 b3 = new Blip3("A String ". // s.io.

pero aún así. hay campos que no queremos que se serialicen. Capítulo 7: E/S con Java. Cursos de Verano de Málaga .2005 -21- Más sobre serialización * Si no queremos implementar Externalizable para ahorrarnos escribir los métodos writeObject() y readObject(). * Comprobar que ocurre cuando dos objetos que tienen un campo objeto en común se serializan. podemos hacerlo precediendo la declaración de dichos campos del modificador transient.Programación en Java. y luego se recuperan. por tanto. que por defecto es la dirección de memoria en que se encuentra el objeto. * transient viene a indicar que el campo no forma parte del estado del objeto y que. ¿El sistema duplica el campo común o no? S G R * Para visualizar el valor de un manejador podemos sacar su valor hashCode(). . no hace falta guardarlo.

println(t).out. c).println(t). cadena = b.out.readObject(). System. } catch (Exception e) { e.dat")).close(). try { ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("out. System.out. ObjectInputStream in = new ObjectInputStream( new FileInputStream("out. } public static void main(String[] args) { String c = "común".close(). in. t = (Prueba)in.println(s).Programación en Java. s = (Prueba)in. String b) { nombre = a.*.println(s).out.writeObject(t). public class Prueba implements Serializable { String nombre. String cadena. out. Cursos de Verano de Málaga .printStackTrace(). else return nombre + nombre. s = t = null. Prueba s = new Prueba("Alfredo". System.io. out. System. out. . System.2005 -22- Ejemplo import java. } } } Capítulo 7: E/S con Java.out. t = new Prueba("Luis".writeObject(s). System.println(t).readObject(). } public String toString() { if (this == null) return "nada".hashCode().println(s).dat")).hashCode() + cadena + cadena.out. public Prueba() {} public Prueba(String a. c).

Asímismo. . etc.Programación en Java. durante la ejecución.class. Field. Constructor. la clase Object posee el método getClass(). por cada clase que hay cargada. Capítulo 8: Metaclases. * Ese objeto de tipo Class se utiliza en tiempo de ejecución para chequear las conversiones de tipo efectuadas por el programador. Java mantiene un objeto oculto de tipo Class que R describe a dicha clase. * Java suministra un conjunto de metaclases con este objetivo: Class. Cursos de Verano de Málaga . Method. * El operador instanceof nos dice si un objeto es instancia de una clase determinada o no. S G * La verdad es que.2005 -1- Capítulo 8 Metaclases * Las metaclases permiten saber el tipo exacto de un objeto cuando lo único que se tiene es un manejador a su clase base. que permite obtener un objeto de tipo Class con toda la información sobre el verdadero objeto apuntado.class correspondiente a una clase cualquiera Xxx puede obtenerse sencillamente mediante la expresión Xxx. * El objeto .

ShootsThings { FancyToy() { super(1). } } Capítulo 8: Metaclases.println( "Class name: " + cc.getInterfaces(). i++) printInfo(faces[i]).getClass()).isInterface() + "]").java // Copyright (c) Bruce Eckel. Object o = null. i < faces. try { // Requires default constructor: o = cy. try { c = Class. } static void printInfo(Class cc) { System. } } public class ToyTest { public static void main(String[] args) { Class c = null. Class cy = c.Programación en Java.forName("FancyToy").getSuperclass().newInstance(). 1998 // Source code file from the book "Thinking in Java" // Testing class Class interface HasBatteries {} interface Waterproof {} interface ShootsThings {} class Toy { // Comment out the following default // constructor to see // NoSuchMethodError from (*1*) Toy() {} Toy(int i) {} } class FancyToy extends Toy implements HasBatteries.length. for(int i = 0. Class[] faces = c.2005 -2- Ejemplo //: ToyTest. // (*1*) } catch(InstantiationException e) {} catch(IllegalAccessException e) {} printInfo(o.getName() + " is interface? [" + cc. } catch(ClassNotFoundException e) {} printInfo(c). Cursos de Verano de Málaga . .out. Waterproof.

Programación en Java. } } . String stmt) { Collection<T> result = new ArrayList<T>().class equivale a Class<Serializable>. /* Ejecutar una sentencia SQL con JDBC*/ for (/* iterate over jdbc results */ ) { T item = factory. } podría llamarse como: select(new Factory<EmpInfo>(){ public EmpInfo make() { return new EmpInfo().class equivale a Class<String> y Serializable. } return result. lo que puede usarse a la hora de crear objetos de un tipo concreto mediante reflexión.add(item).make(). y no un // Object } public <T> Collection<T> select(Factory<T> factory. Ej.2005 -3- Metaclases en JDK 5 * Uno de los cambios de la JDK 1. * En concreto. /* Usar reflexión y cargar los campos a partir del resultado de la consulta SQL */ result. la función newInstance() de la clase Class ahora retorna un tipo T.: interface Factory<T> { T make(). ”SELECT * FROM EMPLEADOS”). Cursos de Verano de Málaga . S G R Capítulo 8: Metaclases. // Se puede devolver // una T.5 es que la clase Class es genérica. . Así String.

Programación en Java. Cursos de Verano de Málaga - 2005

-1-

Capítulo 9 Copias
* Se denomina alias al efecto según el cual un mismo objeto puede ser gestionado a través de más de un manejador. * Los alias tienen la particularidad de que producen efectos laterales en los objetos apuntados. * Cuando se pasa un manejador como argumento a un método, en dicho método se está creando un alias, ya que el manejador se pasa por valor, y por ende, el objeto apuntado se pasa por referencia.
//: Alias2.java // Copyright (c) Bruce Eckel, 1998 // Source code file from the book "Thinking in Java" // Method calls implicitly alias their // arguments. public class Alias2 { int i; Alias2(int ii) { i = ii; } static void f(Alias2 handle) { handle.i++; System.out.println("handle: " + handle.j); } public static void main(String[] args) { Alias2 x = new Alias2(7); System.out.println("x: " + x.i); System.out.println("Calling f(x)"); f(x); System.out.println("x: " + x.i); } }

S G R

Capítulo 9: Copias.

Programación en Java. Cursos de Verano de Málaga - 2005

-2-

Copias locales
* Cuando pasan cosas así, hay que decidir si puede ser peligroso, si el que usa la clase modificadora no está al tanto de dicho mecanismo. * Si se necesita modificar un argumento dentro de un método, pero no se quiere propagar dicha modificación al exterior, el método puede hacer una copia local para su gestión interna, y no tocar, así, el objeto de entrada. * Para entender esto bien, hay que tener muy claros los siguientes 6 puntos:

- El alias es automático por el mero hecho de pasar un parámetro a un método. - No existen objetos locales, sino manejadores locales. - Hay ámbito para los manejadores, pero no para los objetos. - La vida de un objeto no es problema nuestro. Para eso está el recolector de basura. - No hay forma de evitar que un método modifique su parámetro de entrada. - Los objetos no se pasan como parámetros, sino manejadores a objetos.

Capítulo 9: Copias.

Programación en Java. Cursos de Verano de Málaga - 2005

-3-

Copias locales
* Para hacer una copia local de un objeto, se hace uso del método clone() que está definido en Object como private, y que debemos reescribir como public en nuestra clase.
// Method calls explicitly clones their argument. public class NoAlias2 implements Cloneable { int i; NoAlias2(int ii) { i = ii; } public Object clone() throws CloneNotSupportedException { Object interno; interno = super.clone(); return interno; } static void f(NoAlias2 handle) { try { NoAlias2 copiaHandle = (NoAlias2)handle.clone(); copiaHandle.i++; System.out.println("copiaHandle: " + copiaHandle.i); } catch (Exception e) { System.out.println("Mal está el asunto."); } } public static void main(String[] args) { NoAlias2 x = new NoAlias2(7); System.out.println("x: " + x.i); System.out.println("Calling f(x)"); f(x); System.out.println("x: " + x.i); } }

S G R

* La llamada a super.clone() es fundamental, y se encarga de: - Ubicar la memoria necesaria. - Hacer una copia bit a bit del objeto actual.
Capítulo 9: Copias.

Programación en Java. Cursos de Verano de Málaga - 2005

-4-

Ejemplo
* De lo anterior se deduce que no se hacen copias recursivas de un objeto. O sea, si un objeto A contiene a otro B, y se hace A' = A.clone(), se obtendrá que A y A' contienen manejadores distintos al mismo B: B posee aliases. * Para que no ocurra esto, el método clone() de la clase de A debe: - Efectuar una llamada a super.clone(). - Hacer un clone() para cada uno de los manejadores que contenga.
//: DeepCopy.java // Copyright (c) Bruce Eckel, 1998 // Source code file from the book "Thinking in Java" // Cloning a composed object class DepthReading implements Cloneable { private double depth; public DepthReading(double depth) { this.depth = depth; } public Object clone() { Object o = null; try { o = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return o; } } class TemperatureReading implements Cloneable { private long time; private double temperature; public TemperatureReading(double temperature) { time = System.currentTimeMillis(); this.temperature = temperature; } public Object clone() { Object o = null; try { o = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return o; } } class OceanReading implements Cloneable { private DepthReading depth; private TemperatureReading temperature; public OceanReading(double tdata, double ddata){ temperature = new TemperatureReading(tdata); depth = new DepthReading(ddata); } public Object clone() { OceanReading o = null; try { o = (OceanReading)super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } // Must clone handles: o.depth = (DepthReading)o.depth.clone(); o.temperature = (TemperatureReading)o.temperature.clone(); return o; // Upcasts back to Object } } public class DeepCopy { public static void main(String[] args) { OceanReading reading = new OceanReading(33.9, 100.5); // Now clone it: OceanReading r = (OceanReading)reading.clone(); } }

Capítulo 9: Copias.

Programación en Java. Cursos de Verano de Málaga - 2005

-1-

Capítulo 10 Concurrencia
* Java permite la multitarea, o sea, la existencia simultánea de distintos objetos ejecutando alguno de sus métodos a la vez. A cada una de estas tareas, Java las llama thread. * Para ello existen dos opciones fundamentales: - Heredar de la clase Thread. Tiene la ventaja de que facilita la gestión del thread. - Implementar la interfaz Runnable. Tiene la ventaja de que permite heredar de una clase propia, a la vez que se crea un thread. * Cualquiera que sea la opción elegida, el objeto debe poseer un método llamado run() que comenzará a ejecutarse cuando se arranque el funcionamiento del objeto, mediante el mensaje start().
// ThreadEscritor.java //Thread que escribe un mensaje continuamente public class ThreadEscritor extends Thread { String interno; public ThreadEscritor (String msg) { super(); interno = msg + "\t"; } public void run() { while (true) { System.out.println(interno); yield(); } } public static void main(String[] args) { // Esto crea los threads, llamando a sus constructores.

S G R

ThreadEscritor uno = new ThreadEscritor("Uno"); ThreadEscritor dos = new ThreadEscritor("Dos"); // Esto empieza a ejecutar ambos threads. uno.start(); dos.start(); // Nos dormismos durante un rato, y mientras // los otros se siguen ejecutando. try { Thread.currentThread().sleep(10000); } catch (InterruptedException e) { } finally { System.exit(0); } } }

Capítulo 10: Concurrencia.

* Un thread se clasifica como daemon con setDaemon(Boolean n). Para ello basta con llamar a start() justo cuando creamos el objeto. y se hace tx. * Véase también la función estática currentThread() que devuelve un manejador al thread actual. antes de hacer tx. interno = msg + "\t". } } public static void main(String[] args) { // Esto crea los threads. llamando a sus constructores.java //Thread que escribe un mensaje continuamente public class ThreadEscritor extends Thread { String interno.2005 -2- Concurrencia * También es posible arrancar a ejecutar un objeto en el mismo momento de su creación. // Nos dormimos durante un rato. } public void run() { while (true) { System. y mientras // los otros se siguen ejecutando. start().exit(0). pero como aún hay dos threads más ejecutándose. Cursos de Verano de Málaga . el sistema no da por acabada la ejecución del programa. // ThreadEscritor. .sleep(10000). acabará el programa main() (que se considera otro thread). el programa anterior acabaría si se quita el System. ThreadEscritor dos = new ThreadEscritor("Dos"). } catch (InterruptedException e) { } finally { System.setDaemon(true). public ThreadEscritor (String msg) { super(). Así. } } } * Nótese la utilización de System.start().out. try { Thread. Capítulo 10: Concurrencia. ThreadEscritor uno = new ThreadEscritor("Uno").println(interno).exit(0) para acabar la ejecución de la aplicación Java completa.Programación en Java.exit(0). yield().currentThread(). Si no se pone.

y mientras // los otros se siguen ejecutando. t2. * Para solucionar el problema aparece la interfaz Runnable.out.sleep(10000). Runnable obliga únicamente a que exista el método run(). t1. public ThreadEscritor (String msg) { interno = msg + "\t".yield(). sino a través de de la propia clase (yield() es static). Thread. } public void run() { while (true) { System. } } } * Nótese que ahora que ThreadEscritor no hereda de Thread. Thread t2 = new Thread(dos). S G R ThreadEscritor dos = new ThreadEscritor("Dos"). Cursos de Verano de Málaga . * Un objeto que herede de Runnable se puede comenzar a ejecutar pasándolo como parámetro a un constructor de Thread. try { Thread.java //Thread que escribe un mensaje continuamente public class ThreadEscritor implements Runnable { String interno. } } public static void main(String[] args) { // Esto crea los objetos.Programación en Java. // Arrancamos los threads creados.exit(0). llamando a sus constructores. . porque Java no permite herencia múltiple. // Esto crea los threads en base a los objetos // que implementan Runnable. Capítulo 10: Concurrencia.2005 -3- Concurrencia * Que la clase que implementa el método run() tenga que heredar de Thread es un inconveniente.println(interno). ThreadEscritor uno = new ThreadEscritor("Uno"). el ejemplo anterior quedaría: // ThreadEscritor.start().ej.. // Nos dormimos durante un rato. no puede llamar directamente a yield(). } catch (InterruptedException e) { } finally { System. Thread t1 = new Thread(uno).currentThread(). P.start().

public Mogollon(String msg) { interno = msg.out."). while (tiempoInicial + 5000 > System. o sea. // Mogollon. i++) { (new Thread(new Mogollon("Thread " + i + ": "))). } public void run(){ if (tiempoInicial == 0) tiempoInicial = System. } } public static void main(String[] args) { for (int i = 0.currentTimeMillis()) { ejecuciones += 1. Cursos de Verano de Málaga .start(). Thread."). . System.yield().Programación en Java.2005 -4- Concurrencia * Un programa Java acaba cuando acaban todos sus threads o cuando los únicos threads que quedan están clasificados como daemons. el planificador de tareas de Java sí lo hace. despachadores de servicios.println("Esto es todo.out. Aunque no guardamos ninguna referencia directa a esos objetos. i < 10. } while (Thread. * En el siguiente ejemplo vemos la creación de un número indefinido de objetos que se convierten en threads y de ahí se comienza su ejecución.activeCount() >1) {} System. private int ejecuciones = 0.java // Esto crea 10 threads funcionando a la vez. } } Capítulo 10: Concurrencia. public class Mogollon implements Runnable { private long tiempoInicial = 0. private String interno. por lo que no son recogidos como basura hasta que acaban su ejecución.println(interno + " se ha ejecutado " + ejecuciones + " veces.currentTimeMillis().

} } public static void main(String[] args) { for (int i = 0. Para ello. int i) { interno = msg. } System. private int numero.Programación en Java. Thread. private String interno.start(). public class Mogollon implements Runnable { final static int NUMERO_DE_THREADS = 10. // Mogollon. que se les asigna con setPriority() y que se puede saber con getPriority(). } } S G R Capítulo 10: Concurrencia.out. * Los threads también pueden tener una prioridad. Cursos de Verano de Málaga .out.println(interno + " se ha ejecutado " + ejecuciones[numero] + " veces.MIN_PRIORITY).java // Esto crea 10 threads funcionando a la vez. while (tiempoInicial + 15000 > System.2005 -5- Concurrencia * Un thread puede tener asociado un nombre. numero = i. i < NUMERO_DE_THREADS.").println("Esto es todo. } public void run(){ if (tiempoInicial == 0) tiempoInicial = System. private static int[] ejecuciones = new int[NUMERO_DE_THREADS].yield(). Un thread puede saber su nombre con getName(). . } while (Thread. i < NUMERO_DE_THREADS. i++) { System.print("["+i+":"+ejecuciones[i]+"]"). i)).out. lo cual facilita las labores de depuración.setPriority((i%3 == 0)? Thread. i++) { Thread t = new Thread(new Mogollon("Thread " + i + ": ". t.MAX_PRIORITY : Thread.currentTimeMillis(). t. private long tiempoInicial = 0.currentTimeMillis()) { ejecuciones[numero] += 1."). System. el nombre se le puede asignar en el mismo momento en que se crea el Thread o bien con setName().activeCount() > 1) {} for (int i = 0. public Mogollon(String msg.

a menudo comparten objetos. En estas circunstancias. * Este mismo efecto lo produce synchronized cuando es aplicado a un método estático. . .Quitarle el synchronized. Suele ser necesario hacer que el acceso a esos objetos se haga de forma atómica. el objeto se bloquea.2005 -6- La palabra synchronized * Cuando hay muchos threads funcionando. sólo uno de los objetos podrá entrar a ejecutar el método estático sincronizado. o incluso zonas de memoria. . Capítulo 10: Concurrencia. Cursos de Verano de Málaga . y ya no acepta más mensajes synchronized por parte de nadie. Cuando se llama a un método synchronized de un objeto . . cada objeto posee (de forma automática) una región crítica o monitor.Probar a ejecutar el siguiente ejemplo.Dejarle el synchronized y quitarle el static. * Para ello.Programación en Java.

print("["+i+":"+ejecuciones[i]+"]"). i < NUMERO_DE_THREADS. t. . numero = i. private long tiempoInicial = 0. int i) { interno = msg. Cursos de Verano de Málaga . i++) { ejecuciones[n] += 1. i < 100. int n) { for (int i = 0.Programación en Java.java // Esto crea 10 threads funcionando a la vez sincronizadamente.println("Esto es todo. } } synchronized static int miRun(String s. private String interno."). i++) { System. public Mogollon(String msg.start(). System.out. i++) { Thread t = new Thread(new Mogollon("Thread " + i + ": ". } while (Thread."). } synchronized public void run(){ if (tiempoInicial == 0) tiempoInicial = System. private static int[] ejecuciones = new int[NUMERO_DE_THREADS].out. public class Mogollon implements Runnable { final static int NUMERO_DE_THREADS = 10.out.2005 -7- La palabra synchronized // Mogollon. } return n. numero).currentTimeMillis(). private int numero. i < NUMERO_DE_THREADS.currentTimeMillis()) { miRun(interno. while(true){} } } S G R Capítulo 10: Concurrencia.activeCount() > 1) {} totales().println(s + " se ha ejecutado " + ejecuciones[n] + " veces. } } public static void main(String[] args) { for (int i = 0. while (tiempoInicial + 5000 > System. } public static void totales(){ for (int i = 0. System. i)).

Ha recibido el mensaje suspend(). Está a la espera de recibir un notify() o un notifyAll(). El thread está dormido.Programación en Java.Está en espera de entrar en un método synchronized en ejecución por parte de otro objeto.Nuevo: El thread ha sido creado. .2005 -8- Estados de un thread * Un thread puede estar en cuatro estados: . El par wait()-notify() sólo puede aparecer en métodos sincronizados. pero aún no se ha llamado a start(). .Ejecutable: El thread está en disposición de ser ejecutado.Bloqueado: Hay alguna circunstancia que evita que el thread esté en disposición de ejecutarse. . . Capítulo 10: Concurrencia. o incluso se está ejecutando. cuando son ejecutados en un método sincronizado. Se despertará una vez transcurrido dicho tiempo.Está esperando a completar alguna operación de E/S. .Muerto: El thread ha finalizado su método run(). Un thread puede estar bloqueado porque: .Ha ejecutado un wait(). . mientras que el segundo sí.Ha ejecutado un sleep(nº de milisegundos). Se quedará bloqueado hasta que reciba el mensaje resume(). . . el primero no libera al monitor mientras está bloqueado. * Los pares suspend()-resume() y wait()-notify() varían en que. Cursos de Verano de Málaga .

Orden padre. } S G R synchronized public void run() { /*System.*/ if (extremoFinal . else { while (a[j] > medio) j--. j--.java // Esto ordena un array de 1000 enteros a través de threads. public class Orden implements Runnable { final static int NUMERO_DE_ENTEROS = 100.println("En el run").Programación en Java.*. extremoFinal. while (i <= j) { if (a[i] < medio) i++. } } } Capítulo 10: Concurrencia. byte enEspera. Cursos de Verano de Málaga . if (i <= j) { int aux = a[i]. Orden p){ extremoInicio = i. import java. } synchronized public void meDuermo(byte n) throws InterruptedException { enEspera = n. Orden() {} Orden(int i. if (enEspera == 0) notify().out. wait(). int f. int extremoInicio. static int[] a = new int[NUMERO_DE_ENTEROS]. padre = p. extremoFinal = f.util. j = extremoFinal. } synchronized public void despierta() { enEspera--. i++. a[i] = a[j].extremoInicio > 0) { int medio = a[(extremoFinal+extremoInicio)/2]. .2005 -9- Ejemplo final // Orden. a[j] = aux. int i = extremoInicio.

i < NUMERO_DE_ENTEROS. for (int i = 1.nextInt())% 93.isAlive()) {} for (int i = 0.despierta().1] * 53 % 93. .out. i++) System. Cursos de Verano de Málaga .2005 -10- Ejemplo final Thread o1 = new Thread(new Orden(extremoInicio. o1.out. while (true) {} } } Capítulo 10: Concurrencia.start(). } Thread o = new Thread(new Orden(0.out. j. /*System. try { meDuermo((byte)2).print(a[i]+"."). a[0] = Math. o. // Esto no se debe hacer porque consume recursos."). } catch (InterruptedException e) {} } padre. System. extremoFinal. i < NUMERO_DE_ENTEROS.abs((new Random()). this)).start(). o2.Programación en Java. Thread o2 = new Thread(new Orden(i.println("Saliendo del run").start(). while (o.print(a[i]+". i++) { a[i] = a[i . NUMERO_DE_ENTEROS-1.*/ } public static void main (String[] args) { // Rellena el array con números aleatorios. new Orden())). this)).

y la recoge. sobre cada uno de los cuales se pueden efectuar ciertas acciones. aceptar una tecla. * Los componentes se distribuyen de forma jerárquica. emitiendo un mensaje. creando un evento que debe ser tratado por el componente correspondiente. copiando algo al portapapeles. Cursos de Verano de Málaga . . S G R Capítulo 11: Programación Windows con Java. cada uno de estos componentes acepta un conjunto de operaciones: ser pulsado.Programación en Java. de una ventana en la que se integra. Windows con Java * Programar bajo Windows implica utilizar una nueva disciplina de programación: la programación orientada a eventos. menús. * Estos componentes son botones. Cuando el usuario efectúa una de estas operaciones el sistema Windows se da cuenta. ventanas. etc. en última instancia.2005 -1- Capítulo 11 Prog. ser escrito. paneles para visualización de cosas. ser arrastrado. etc. * Al igual que en la vida real. * Windows envía el evento al componente. etc. dependiendo siempre. imágenes. * Un programa está formado por un conjunto de componentes. * Se dice que un componente tiene el foco cuando es el componente actualmente seleccionado por el usuario. y éste lo trata como sea: grabando un fichero.

además debe poseer una función paint() en la que se dibuje la información necesaria.No tiene acceso al disco duro del ordenador cliente.Necesita de un navegador para ser ejecutado. * Todo applet debe heredar de una clase denominada Applet.2005 -2- Applets y aplicaciones independientes * Java permite la creación de aplicaciones Windows independientes. y de aplicaciones para uso en Internet.No puede contener menúes (sí con Java Swing). incluído texto con drawString(). Cursos de Verano de Málaga . . Capítulo 11: Programación Windows con Java. más que al servidor del que proviene. * Un applet tiene las siguientes restricciones: . a través de un navegador: lo que se llaman applets.html que lo incluya. * paint() recibe como parámetro un objeto de tipo Graphics que es el lugar que el navegador reserva para realizar el dibujo.No tiene acceso a ningún ordenador de Internet. * Un objeto de tipo Graphics posee operaciones para dibujar distintas figuras. y de una página . . . .Programación en Java.

drawString("¡El primer applet ya. Cursos de Verano de Málaga .applet.Applet.class width=300 height=80> Applets no soportados. import java.html que lo utiliza es: <html> <head> <title>El primer applet </title> </head> <body> <hr> <applet code=Primer.!". public class Primer extends Applet { public void paint(Graphics g){ g.Programación en Java.java import java.Graphics. 25).awt. . </applet> <hr> </body> </html> S G R Capítulo 11: Programación Windows con Java. 20. } } * El fichero .2005 -3- El primer applet // Primer.

* Entre <APPLET> y >/APPLET> pueden aparecer cuantas etiquetas PARAM se quiera.Programación en Java. alt: Texto que visualizarán los navegadores que no tienen Java. name: Nombre que puede darse al applet. . hspace: Espacio en pixels que el navegador dejará a ambos lados del applet. align: Tiene el mismo sentido que en la etiqueta <IMG>. constituidas por dos elementos: name: Nombre del parámetro. value: Valor de dicho parámetro.class que contiene el applet a ejecutar. y puede contener: archive: Nombre del fichero .jar entero. El navegador se traerá al fichero . Este nombre es el que hay que mandar al método getApplet() para saber si dicho applet está en ejecución o no. Capítulo 11: Programación Windows con Java. vspace: Espacio en pixels que el navegador dejará por encima y por debajo del applet. pero que saben interpretar la etiqueta applet. codebase: Indica la URL en la que podemos encontrar el fichero . width: Anchuro reservada para el applet. Cursos de Verano de Málaga . que son: code: Nombre de la clase a ejecutar.2005 -4- La etiqueta applet * La etiqueta APPLET contiene tres elementos. height: Altura reservada para el applet.jar que contiene a la clase a ejecutar.

import java.fillOval(50.red).yellow). 300).Programación en Java. import java. Font.BOLD. 600.fillRect(50. se tiene el siguiente ejemplo: // Primer. g. g. } } S G R Capítulo 11: Programación Windows con Java. g.applet. g.Graphics.setColor(Color.awt. .Applet. 300).setColor(Color. // Círculo azul.Font. en cuanto a fuentes y colores.drawString("Viva la feria y la playa. g.2005 -5- Fuentes y Colores * Para ilustrar las posibilidades de esto.awt. import java. g. g. 600. 175). 25)).fillOval(200.setColor(Color. Cursos de Verano de Málaga .red).awt. g. 180.setFont(new Font("Helvetica".java import java. // Letras en blanco. public class Primer extends Applet { public void paint(Graphics g){ // Rectángulo amarillo. g.setColor(Color. 300.white). 25.Color. 25. // "valo rojo. 25. 300).".

6.Se llama al método init(). el navegador llamará a stop() para parar el applet.. Normalmente start() se encarga de lanzar uno o más threads. start() será invocado cada vez que se quiera que se reinicie la ejecución. Cursos de Verano de Málaga .Si el usuario se va a otra página. 4. el navegador mantiene al applet en memoria.A pesar de que el usuario cambie de página y se mueva por Internet.. 5..Se carga la clase que se haya indicado en la etiqueta code.Programación en Java. mientras el applet esté activo. 4 y 5 pueden repetirse muchas veces.Cuando el navegador ya no necesita más el código del applet. 3. stop() deberá pararlos. sufre la siguiente secuencia de mensajes: 1..El navegador irá invocando paint() y otros métodos similares para actualizar la información en pantalla. llama a destroy() y lo quita de memoria. .Se llama al método start() para indicar al applet que comience su ejecución.2005 -6- Ciclo de vida de un applet * Un applet cuando es llamado por el navegador. que se encarga de realizar las operaciones que sólo se vayan a realizar una vez: cargar imágenes por Internet. Capítulo 11: Programación Windows con Java... 2. 7. Si start() lanza threads. por lo que los puntos 3. etc..

su R tipo.class width=800 height=400> <param name=UNO value="Un texto de ejemplo. </applet> <hr> </body> </html> Capítulo 11: Programación Windows con Java. S * La clase Applet incorpora el G método getParameterInfo() que devuelve un array con información sobre cada uno de los parámteros. Sobre cada parámtero se devuelve su nombre. y su descripción. * getParameter() recoge siempre una cadena. * Los parámetros se recogen desde el applet a través de getParameter(). el fichero .56> <param name=DOS value=100> Applets no soportados. .html pasa los parámetros a través de la etiqueta <PARAM>. Cursos de Verano de Málaga .Programación en Java.2005 -7- Paso de parámetros en un applet * Como hemos visto. <html> <head> <title>El primer applet </title> </head> <body> <hr> <applet code=Primer. que admite como parámetro una cadena con el nombre de parámetro a recuperar."> <param name=TRES value=102. por lo que si el parámetro es numérico habrá que transformarlo convenientemente.

uno = getParameter(PARAM_UNO). } catch (NumberFormatException e) { tres = (float)0. Cursos de Verano de Málaga . "Float". } catch (NumberFormatException e) { dos = 0. private static final String PARAM_DOS = "DOS". 180.valueOf(getParameter(PARAM_TRES))). private static String uno." }.Applet. public class Primer extends Applet { private static final String PARAM_UNO = "UNO".0." } }. "Parámetro de prueba tipo textual. 200). private static float tres. 180. g. { PARAM_DOS. "Entero". .init().Programación en Java. private static final String PARAM_TRES = "TRES". if (uno == null) uno = new String("Valor por defecto"). return retorno. { PARAM_TRES.floatValue().parseInt(getParameter(PARAM_DOS)).2005 -8- Recuperación de parámetros desde un applet * El programa Java correspondiente es: // Primer. } try { tres = (Double.drawString(uno + " " + dos + " " + tres. try { dos = Integer.java import java.Graphics. } } public void paint(Graphics g){ g. public String[][] getParameterInfo() { String[][] retorno = { { PARAM_UNO." }. // Captura de parámetros. "Parámetro de prueba tipo float. } public void init() { // Inicializa la clase padre. "Parámetro de prueba tipo entero. } } Capítulo 11: Programación Windows con Java. "Texto". super.awt.drawString("Estos son los valores de los parámetros:".applet. import java. 175). private static int dos.

. Véase la clase AudioClip R. .Image getImage(). y posee. Véase la clase Image.void showStatus(String). . Obtiene una imagen. Obtiene un fichero de sonido. Mira a ver si el applet especificado está o no en ejecución. Capítulo 11: Programación Windows con Java. Devuelve un iterador con todos los applets en ejecucuión.2005 -9- Comunicación con el navegador * Es de especial importancia en el ámbito de los applets el método getAppletContext(). . .Enumeration getApplets(). que devuelve un objeto que implementa la interfaz AppletContext. S G . Saca un mensaje por la barra de estado del navegador. Este objeto es construído por el propio navegador. los siguientes métodos: .AudioClip getAudioClip(URL).void showDocument(URL). Indica al navegador que visualice la página especificada. Cursos de Verano de Málaga .Programación en Java.Applet getApplet(String). entre otros.

si cabe.Programación en Java. ya que no tienen las restricciones de los applets. . * La librería AWT (Abstract Windows Toolkit) suministra todos los componentes necesarios para aplicaciones Windows. a la que se van añadiendo los componentes que queremos que integren nuestra aplicación. Cursos de Verano de Málaga . * La jerarquía básica de AWT es la siguiente: * Toda aplicación Windows suele comenzar en una clase que hereda de Frame (o bien activa un Frame). Esto componentes han sido extendidos en la librería Swing de la JFC (Java Fundation Classes). Capítulo 11: Programación Windows con Java. que los applets son las aplicaciones independientes.2005 -10- Ventanas * Más interesante.

y se visualiza. } queremos que se distribuyan los componentes que se van añadiendo. se le dota de un tamaño.resize(200. public class Primer extends Frame { Button b1 = new Button("Aceptar").Programación en Java.CENTER. * Tras crear el Frame.java import java. y además los botones no hacen nada. } S * La ventana (Frame) posee dos botones que se le añaden con G add() en el constructor. * La aplicación arranca desde un main(). f. public Primer() { setLayout(new FlowLayout(FlowLayout. Cursos de Verano de Málaga .*. b2 = new Button("Cancelar"). 20)). . al igual que cualquier otra aplicación independiente. } public static void main(String[] args) { Primer f = new Primer(). Esto se consigue con setLayout(). 300).show(). f. R hay que decidir cómo * Antes de añadir ningún componente. 20.2005 -11- Primer ejemplo de ventana // Primer. add(b1). add(b2).awt. * Nota: Es imposible cerrar la ventana. Capítulo 11: Programación Windows con Java.

* Cualquier Container tiene operaciones para indicar cual es su distribuidor.BorderLayout. y para añadir componentes: setLayout() y add() respectivamente. . Este no lo vamos a estudiar. .CardLayout. Capítulo 11: Programación Windows con Java.FlowLayout. .2005 -12- Distribución de componentes: Layout.GridBagLayout. el distribuidor redistribuye los componentes de acuerdo a unas reglas. de manera que si ésta se redimensiona.GridLayout. * Los tipos de Layout que hay son los siguientes: . * La forma en que los componentes se distribuyen por la ventana viene dada por un distribuidor (Layout). Cursos de Verano de Málaga . .Programación en Java. . * Los distribuidores se adaptan a las dimensiones de la ventana.

400).out. } return super. } public static void main(String[] ars) { FlowLayout1 f = new FlowLayout1().*. } public boolean handleEvent(Event e) { if (e.2005 -13- FlowLayout * Este distribuidor va colocando los componentes de izquierda a derecha. . for(int i = 0.show().java // Demonstrating the FlowLayout import java.id == Event.").handleEvent(e). f. System.Programación en Java. Cursos de Verano de Málaga . i++) add(new Button("Button " + i)).println("Frame eliminado. public class FlowLayout1 extends Frame { public FlowLayout1() { setLayout(new FlowLayout()). y de arriba abajo.target == this) { System.WINDOW_DESTROY && e. f. } } S G R Capítulo 11: Programación Windows con Java. i < 20.exit(0).setSize(300. //: FlowLayout1.awt.

} return super.").id == Event. f. .show().WINDOW_DESTROY && e. add("South". } public boolean handleEvent(Event e) { if (e. o en el centro. setLayout(new BorderLayout()). new Button("Button " + i++)). System.println("Frame eliminado.Programación en Java. add("Center".handleEvent(e). new Button("Button " + i++)). } } Capítulo 11: Programación Windows con Java.*. add("East". add("North". 200). //: BorderLayout1. add("West".setSize(300. } public static void main(String[] args) { BorderLayout1 f = new BorderLayout1(). public class BorderLayout1 extends Frame { public BorderLayout1() { int i = 0.exit(0).java // Demonstrating the BorderLayout import java. new Button("Button " + i++)).target == this) { System.awt. new Button("Button " + i++)).2005 -14- BorderLayout * Este distribuidor coloca las cosas distribuídas a alguna de los lados. new Button("Button " + i++)). Cursos de Verano de Málaga . f.out.

println("Frame eliminado.handleEvent(e). i++) add(new Button("Button " + i)). //: GridLayout1."). } return super. public class GridLayout1 extends Frame { public GridLayout1() { setLayout(new GridLayout(7. } public boolean handleEvent(Event e) { if (e. 3)). } public static void main(String[] ars) { GridLayout1 f = new GridLayout1().2005 -15- GridLayout * Este distribuidor va colocando los componentes de izquierda a derecha.id == Event. S G R . for(int i = 0. f.awt.Programación en Java. según una rejilla cuyo tamaño se especifica en el constructor.exit(0). System.show().java // Demonstrating the GridLayout import java. i < 20. } } Capítulo 11: Programación Windows con Java.*.out. f. y de arriba abajo. Cursos de Verano de Málaga .setSize(300.target == this) { System.WINDOW_DESTROY && e. 400).

. cards.equals(third)) { cl."). } public boolean handleEvent(Event e) { if (e. new Button(id)). p. p. } else if (evt. add("Center".Applet. p.2005 -16- CardLayout * Este distribuidor va colocando los componentes unos encima de otros. new ButtonPanel("The first one")). //: CardLayout1.add("First card".target. add("North". p. Panel cards = new Panel().applet. de manera que pueden ser seleccionados alternativamente mediante botones o cualquier otro sistema similar.add("Second card". 200).Programación en Java.setSize(300. cards. } } Capítulo 11: Programación Windows con Java. } return super. f.last(cards). new ButtonPanel("The third one")). add("Center". } public static void main(String[] args) { CardLayout1 f = new CardLayout1().*. cards.handleEvent(e). } public boolean action(Event evt. Object arg) { if (evt.action(evt.next(cards).out. arg). CardLayout cl = new CardLayout().show(). cl.setLayout(new FlowLayout()).equals(second)) { cl. cards. cards).add("Third card". public CardLayout1() { setLayout(new BorderLayout()). System. } else if (evt. import java.exit(0).add(second).equals(first)) { cl.WINDOW_DESTROY && e.id == Event.first(cards). return true. p). } } public class CardLayout1 extends Frame { Button first = new Button("First").add(first).setLayout(cl).target. second = new Button("Second"). class ButtonPanel extends Panel { ButtonPanel(String id) { setLayout(new BorderLayout()).java // Demonstrating the CardLayout import java. f.target.target == this) { System.first(cards).awt.println("Frame eliminado. new ButtonPanel("The second one")). Cursos de Verano de Málaga .add(third). } else return super. third = new Button("Third"). Panel p = new Panel().

* La primera de ellas es horrorosa. o el intento por parte del usuario de cerrar la ventana. El segundo lo ignoraremos. * La segunda es mucho más cómoda. haremos que lo genere nuestro padre. que se llama Versión 1.1 de Java. Si el evento no se puede manejar. Capítulo 11: Programación Windows con Java. como pueda ser la pulsación de un botón. Cursos de Verano de Málaga . . y al que se le pasan dos parámetros: uno de tipo Event que posee toda la información del evento. R * Este if va dentro del método action(). pero hay que aprenderla porque es la que poseen muchos navegadores aún no adaptados al nuevo sistema. y es la que se emplea en la versión 1. * Un objeto de tipo Event tiene un campo target que contiene al objeto que ha recibido el evento. S * Crear un enorme if en cascada Gpara detectar el componente al que va dirigido el evento. * action() debe gestionar el evento y retornar true.0 de Java automáticamente cuando se produce un evento.Programación en Java.2005 -17- Manejo de eventos * Hay dos formas básicas de manejar un evento.

").CENTER.out. 20. f.*. } public static void main(String[] args) { Primer f = new Primer(). public class Primer extends Frame { Button b1 = new Button("Aceptar"). b2 = new Button("Cancelar").target. 300). add(b1).target.println("Frame seleccionado.out. add(b2). * handleEvent() se convierte en una cascada de if en los que no sólo hay que controlar quién recibe el evento sino qué evento se ha producido.equals(b2)) System.out.").2005 -18- Ejemplo con action() * En el siguiente ejemplo: // Primer.equals(b1)) System. } } no se detecta nada sobre la ventana original.equals(this)) System. pero no los más complejos. que sólo tiene como argumento el evento producido. else if (e. * Esto se debe a que action() sólo recoge los eventos básicos sobre cada componente. .awt. * Para recoger todo tipo de eventos se emplea handleEvent().println("Botón dos pulsado.action(e. } public boolean action(Event e. o). f. Object o) { if (e. public Primer() { setLayout(new FlowLayout(FlowLayout. Capítulo 11: Programación Windows con Java.java import java.target.resize(200.println("Botón uno pulsado.show().Programación en Java. else return super. Cursos de Verano de Málaga . 20))."). return true. else if (e.

} public boolean handleEvent(Event e) { if (e.action(e.println("Frame eliminado.*.exit(0).show().println("Botón dos pulsado.equals(b2)) System. y puede ser comparado con una delas numerosas constantes especificadores de tipo de evento que posee Event."). Ej. o). add(b2).id == Event. } public boolean action(Event e.awt. * Nada impide tratar los eventos más complejos con handleEvent() y los más simples con action(). public Primer() { setLayout(new FlowLayout(FlowLayout.WINDOW_DESTROY && e.handleEvent(e). else if (e. } S G R public static void main(String[] args) { Primer f = new Primer(). add(b1). .Programación en Java.target.println("Botón uno pulsado. Cursos de Verano de Málaga .equals(b1)) System.target. f."). else return super. 20)).resize(200. Object o) { if (e.out. return true.out. } } Capítulo 11: Programación Windows con Java. System.: // Primer.CENTER.target == this) { System."). } return super. b2 = new Button("Cancelar").java import java.2005 -19- Ejemplo con handleEvent() * El tipo de evento producido aparece en el campo id. 20. public class Primer extends Frame { Button b1 = new Button("Aceptar"). 300).out. f.

public TextField1() { setLayout(new FlowLayout( FlowLayout. } return super.setText("Inserted by Button 2: " + s).java // Using the text field control import java.show().id == Event. System. } // Let the base class handle it: else return super.setEditable(false). 30). Object arg) { if(evt. que permite poner o tomar texto.equals(b2)) { t. 20)). así como la longitud de la línea en caracteres. * Hereda de TextComponent. } } Capítulo 11: Programación Windows con Java.setSize(300.exit(0).awt. TextField t = new TextField("Starting text". b2 = new Button("Set Text").CENTER.Programación en Java. arg). t. .").getText()).out. } public boolean action (Event evt.equals(b1)) { System. add(b1). add(b2).target.length() == 0) s = t.println(t.println("Frame eliminado. public class TextField1 extends Frame { Button b1 = new Button("Get Text").handleEvent(e).action(evt. e indicar si el texto se puede editar o no. if(s. } else if(evt. * El constructor permite indicar el texto inicial. //: TextField1.target.getSelectedText(). String s = new String().target == this) { System.setEditable(true). 200). t. // We've handled it here } public static void main(String[] args) { TextField1 f = new TextField1().out. 20. add(t). Permite operaciones básicas con el portapapeles. f. Cursos de Verano de Málaga . } public boolean handleEvent(Event e) { if (e. f. return true.getText().*. seleccionar texto y cogerlo.WINDOW_DESTROY && e. s = t.2005 -20- TextField * TextField es un área de texto de una sola línea.

public TextArea1() { setLayout(new FlowLayout( FlowLayout.exit(0). } public boolean action (Event evt. 20.equals(b3)) { String s = "-Replacement-". b3 = new Button("Replace Text").CENTER. 1.java // Using the text area control import java.equals(b4)) t2. 20)).length()).setSize(300. A partir de ahora un componente de este puede sustituir a la salida estándar.2005 -21- TextArea * Es igual que TextField. arg). //: TextArea1. reemplazar e insertar texto por enmedio. add(t1).equals(b2)) { t2. Cursos de Verano de Málaga . public class TextArea1 extends Frame { Button b1 = new Button("Text Area 1"). 30). 30). 4. } else if(evt. // Let the base class handle it: else return super. Object arg) { if(evt. 10). return true.show(). add(b2). b2 = new Button("Text Area 2"). t2 = new TextArea("t2". 200). add(b1).*.append(":-" + t1.insert("-Inserted-".action(evt. add(b4).equals(b1)) t1. add(t2). } public boolean handleEvent(Event e) { if (e.target.target."). TextArea t1 = new TextArea("t1".setText("Boton 2").getText()). 3 + s. f.out. } } S G R * TextArea posee un constructor con el que no sólo se indica el contenido y dimensiones iniciales de este componente. y además permite añadir. System. f. t2. excepto porque permite varias líneas. 3.handleEvent(e). Capítulo 11: Programación Windows con Java.target. } return super. .setText("Boton 1").println("Frame eliminado. // We've handled it here } public static void main(String[] args) { TextArea1 f = new TextArea1().target.target == this) { System. sino con el que también es posible indicar si se quieren barrars de desplazamiento.id == Event.WINDOW_DESTROY && e.Programación en Java.replaceRange(s. else if(evt.awt. t2. } else if(evt. add(b3). b4 = new Button("Insert Text"). y a qué lados.

length() == 0) labl3. Button b2 = new Button("Test 2"). return true. f. arg). derecha o centro."). add(labl3).exit(0). } else return super.CENTER).getAlignment() == Label.handleEvent(e).getAlignment() == Label.target == this) { System. } public static void main(String[] args) { Label1 f = new Label1().show(). . Label labl2 = new Label(" ").LEFT) labl3. * En el momento en que se crea la etiqueta se le da un tamaño. } } Capítulo 11: Programación Windows con Java.setAlignment(Label. * También se puede hacer que el texto de la etiqueta esté alineado a izquierda.setText("Text set into Label").java // Using labels import java.RIGHT).Programación en Java. add(labl2). add(labl1).RIGHT).LEFT). add(b1). } public boolean action (Event evt. 20.getAlignment()==Label.target.CENTER) labl3.id == Event.setAlignment(Label. add(t1). Label. } return super. } public boolean handleEvent(Event e) { if (e.equals(b1)) labl2. Cursos de Verano de Málaga . public class Label1 extends Frame { TextField t1 = new TextField("t1".getText().awt.trim(). Object arg) { if(evt. 10).WINDOW_DESTROY && e. Label labl1 = new Label("TextField t1"). add(b2).RIGHT) labl3.*.2005 -22- Label * Permite colocar etiquetas.action(evt. 20)).setSize(300. public Label1() { setLayout(new FlowLayout( FlowLayout. else if(labl3.setAlignment(Label. //: Label1. Button b1 = new Button("Test 1"). if(labl3. por ejemplo para identificar un TextField. else if(labl3. Label labl3 = new Label(" ". 200).CENTER. y recuperarlo con getText().equals(b2)) { if(labl3.println("Frame eliminado.out. f. else if(evt.target.setText("labl3"). Sepuede cambiar el título del la etiqueta con setText(). System.

appendText("Box " + b + " Set\n"). else if(evt. System.equals(cb1)) trace("1".println("Frame eliminado.appendText("Box " + b + " Cleared\n"). arg). public class Checkbox1 extends Frame { TextArea t = new TextArea(6. } public boolean action (Event evt. Checkbox cb1 = new Checkbox("Check Box 1").java // Using check boxes import java.*. boolean state) { if(state) t. return true.getState())."). } } S G R Capítulo 11: Programación Windows con Java. else return super. } void trace(String b.out. Object arg) { if(evt. 20). add(cb1). //: Checkbox1. else if(evt. Checkbox cb2 = new Checkbox("Check Box 2"). Cursos de Verano de Málaga . cb1. * Cada vez que un Checkbox se activa o desactiva. cb2. Checkbox cb3 = new Checkbox("Check Box 3").getState()).target.WINDOW_DESTROY && e.CENTER. } public static void main(String[] args) { Checkbox1 f = new Checkbox1().Programación en Java.show().target. * Se puede saber el estado de un Checkbox mediante getState().target. ocurre un evento como si de un botón se tratase.equals(cb2)) trace("2".id == Event. public Checkbox1() { setLayout(new FlowLayout( FlowLayout. } return super. 200). 20. f.action(evt.2005 -23- Checkbox * Checkbox sirve para hacer un selección binaria. add(cb3). add(t). else t. } public boolean handleEvent(Event e) { if (e.target == this) { System. add(cb2).equals(cb3)) trace("3".handleEvent(e). 20)).awt.setSize(300. cb3. f.exit(0). .getState()).

2005 -24- CheckboxGroup * CheckboxGroup implementa los llamados radio buttons que son una secuencia de Checkbox en los que sólo puede haber activo uno cada vez. g. } public static void main(String[] args) { RadioButton1 f = new RadioButton1(). else if(evt. cb2 = new Checkbox("two". false).target.equals(cb3)) t. 200).out. } public boolean handleEvent(Event e) { if (e. t.setEditable(false). Cursos de Verano de Málaga . false). } } Capítulo 11: Programación Windows con Java. * Antes de visualizar un CheckboxGroup debe haber uno y sólo un Checkbox activado. true). g. System.setText("Radio button 1"). else if(evt. public RadioButton1() { setLayout(new FlowLayout( FlowLayout.target.awt. 20. public class RadioButton1 extends Frame { TextField t = new TextField("Radio button 2".println("Frame eliminado. arg). * Para incluir un Checkbox en un CheckboxGroup hay que hacer uso de un constructor de Checkbox en el que se dice que se lo quiere incluir en un CheckboxGroup y en cual.setText("Radio button 3"). cb3 = new Checkbox("three". add(cb2).handleEvent(e). //: RadioButton1.CENTER. g.equals(cb2)) t.*.WINDOW_DESTROY && e.show().target.id == Event.equals(cb1)) t. 20)). CheckboxGroup g = new CheckboxGroup(). f. .setSize(300. add(t).").target == this) { System. } return super. else return super. Object arg) { if(evt.setText("Radio button 2"). add(cb3).exit(0). } public boolean action (Event evt.Programación en Java. 30). f. add(cb1). Checkbox cb1 = new Checkbox("one".action(evt.java // Using radio buttons import java. return true.

y remove() para eliminar opciones. Object arg) { if(evt. for(int i = 0. 20.exit(0).equals(c)) t. arg).show().CENTER.*. public class Choice1 extends Frame { String[] description = { "Hirviente". Cursos de Verano de Málaga .action(evt.getSelectedIndex() + " " + (String)arg). "Brillante".target. "Primoroso". 200). TextField t = new TextField(30). else if(evt.equals(b)) { if(count < description. "Putrefacto" }. "Amuermante".").println("Frame eliminado. Con Choice sólo se puede escoger un único elemento de la lista.java // Using drop-down lists import java.2005 -25- Choice * Choice no es como el Combo box de Windows. } public boolean action (Event evt. add(c). add(b). } else return super. } return super. } public static void main(String[] args) { Choice1 f = new Choice1().addItem(description[count++]). i++) c.length) c. 20)). * Las opciones se añaden a un Choice con addItem(). int count = 0. aunque es posible añadir nuevos valores dinámicamente.setSize(300. public Choice1() { setLayout(new FlowLayout( FlowLayout. } public boolean handleEvent(Event e) { if (e. f.addItem(description[count++]). "Florido". "Obtuso". //: Choice1. . f. Choice c = new Choice(). "Recalcitrante".Programación en Java. add(t).setEditable(false).setText("index: " + c. t.awt.target.target == this) { System. // Sólo se añaden las 4 primeras. return true.out. La posición del elemento seleccionado se averigua con getSelectedIndex(). También puede usarse getSelectedItem() para recoger la cadena seleccionada.id == Event.handleEvent(e). System. Button b = new Button("Add items").WINDOW_DESTROY && S G R e. i < 4. } } Capítulo 11: Programación Windows con Java.

200).Programación en Java. // Show 6 items. int count = 0. System. //: List1. . Los elementos seleccionados se devuelven en una array mediante getSelectedItems(). f. public class List1 extends Frame { String[] flavors = { "Chocolate".addItem(flavors[count++]. i < items.getSelectedItems(). for(int i = 0. "Chirimoya". 20. "Damasquillos" }.appendText(items[i] + "\n"). "Vainilla".java // Using lists with action() import java.awt.addItem(flavors[count++]). public List1() { setLayout(new FlowLayout( FlowLayout.setEditable(false).setSize(300.2005 -26- List * Una lista ocupa un número concreto de líneas en pantalla. Button b = new Button("test").length. y permite selección múltiple. 20)). t. TextArea t = new TextArea(flavors. add(t). Object arg) { if(evt.length. add(lst). i++) t. Cursos de Verano de Málaga .target.CENTER. } else if(evt. "Pasas". add(b). 0).target.equals(lst)) { t. } return super. 30).out.").equals(b)) { if(count < flavors. String[] items = lst.action(evt. Los elementos también se añaden con addItem(). allow multiple selection: List lst = new List(6.*.show().length) lst. true).target == this) { System. } else return super.exit(0). } } Capítulo 11: Programación Windows con Java.println("Frame eliminado. } public boolean handleEvent(Event e) { if (e. for(int i = 0. i++) lst. } public static void main(String[] args) { List1 f = new List1(). "Fresas". } public boolean action (Event evt. f. arg).handleEvent(e). "Mango".id == Event.setText(""). return true. "Chumbos". i < 4.WINDOW_DESTROY && e.

. . import java. Cada elemento de un menú desplegable.awt.java // Copyright (c) Bruce Eckel. .Programación en Java.Los MenuITem se añaden a los Menu con add(). "Strawberry". Menu s = new Menu("Safety"). new CheckboxMenuItem("Hide") }.Es posible añadir un Menu a otro Menu. 30). public class Menu1 extends Frame { String[] flavors = { "Chocolate".*. "Mint Chip".Esposible incluir separadores en un Menu con addSeparator().El estado de un CheckboxMenuItem se sabe con getState(). pero que le pone al lado una marca si dicha opción está seleccionada. * La forma de trabajar es muy simple: . Menu f = new Menu("File"). "Rum Raisin". "Vanilla Fudge Swirl". La barra de menús. S G R //: Menu1. Capítulo 11: Programación Windows con Java. TextField t = new TextField("No flavor". Igual que MenuItem. Cursos de Verano de Málaga . checkbox menu items // and swapping menus.Los Menu se añaden a los MenuBar con add(). Menu m = new Menu("Flavors"). "Mud Pie" }. MenuBar mb1 = new MenuBar(). . // Alternative approach: CheckboxMenuItem[] safety = { new CheckboxMenuItem("Guard").CheckboxMenuItem.2005 -27- MenuComponent * Esta clase es abstracta. .MenuBar. . Cada menú desplegable de la barra de menús. "Praline Cream". Lo mismo con los CheckboxMenuItem.Un MenuBar se coloca en un Frame con setMenuBar(). . .Con setEnabled() podemos habilitar o inhabilitar cualquier opción. 1998 // Source code file from the book "Thinking in Java" // Menus work only with Frames.MenuItem. // Shows submenus. . "Mocha Almond Fudge". .Menu. y de ella heredan los elementos que componen un menú y que son los siguientes: .

boolean chosen = false. i++) { m. Button b = new Button("Swap Menus").target. // Set up the system for swapping menus: add("North".target.add(s). MenuItem[] other = { new MenuItem("Foo"). for(int i = 0.toString()). i < file. f.length.add(fooBar). t.setText(arg.equals(safety[0])) t.setText("Opening "+ s +". for(int i = 0.target.WINDOW_DESTROY) System. f.equals(flavors[i])) chosen = true. b). // A second menu bar to swap to: MenuBar mb2 = new MenuBar().show().add(new MenuItem(flavors[i])). f. else if(evt. i++) fooBar.target instanceof MenuItem) { if(arg.setEditable(false). else t.length. public Menu1() { for(int i = 0.exit(0). mb2. } else if(evt. if(!chosen) t. new MenuItem("Baz"). Menu fooBar = new Menu("fooBar").getText(). else if (m == mb2) setMenuBar(mb1).length.equals(safety[1])) t. i++) if(s. return true. }.200).add(other[i]).action(evt. } else if(evt. i < flavors.handleEvent(evt).Programación en Java.length. new MenuItem("Exit") }. i < flavors.getState()).resize(300. } else return super. i++) s. if(m == mb1) setMenuBar(mb2). return true.add(m).add(file[i]). } } Capítulo 11: Programación Windows con Java.addSeparator().add(safety[i]). i < other. t).exit(0).getState()).setText("Hide the Ice Cream! " + "Is it cold? " + safety[1].setText("Guard the Ice Cream! " + "Guarding is " + safety[0].equals("Open")) { String s = t.length. } public boolean handleEvent(Event evt) { if(evt. else return super.target. i++) f. mb1. new MenuItem("Bar"). mm!"). Mmm. for(int i = 0. you must match the target: else if(evt. Cursos de Verano de Málaga .setText("Choose a flavor first!").id == Event. mb1.equals(file[1])) System. } for(int i = 0. i < safety. arg).add(f).equals(b)) { MenuBar m = getMenuBar(). else t. } public static void main(String[] args) { Menu1 f = new Menu1(). add("Center". Object arg) { if(evt. } public boolean action(Event evt. setMenuBar(mb1). // CheckboxMenuItems cannot use String // matching. // Add separators at intervals: if((i+1) % 3 == 0) m. .2005 -28- MenuComponent MenuItem[] file = { new MenuItem("Open").

podemos asociar un identificar independiente a cada opción. Runa opción de menú. haremos cuando sepamos que se trata de uso de getActionCommand() para saber cuál es.Programación en Java. con setActionCommand(). . S G * Cuando se quiera preguntar por la opción que se ha escogido.2005 -29- MenuITem setActionCommand() MenuShortCut * Como puede observarse en el ejemplo anterior. * De esta forma podemos cambiar los titulos sin preocuparnos de retocar el código. un componente de un menú (una opción) queda identificado por el propio nombre que aparece en pantalla. Para ello se emplea la clase MenuShortCut. ya que cambiar el título a un menú implica retocar las entrañas del programa. * Para evitar esto. * Por otro lado. * Esto implica un grave problema de internacionalización. Capítulo 11: Programación Windows con Java. Cursos de Verano de Málaga . el constructor de MenuItem permite especificar una tecla paraacceder rápidamente a esa opción del menú.

.mouseDrag() El ratón se está moviendo con un botón pulsado.keyUp() Se ha liberado una tecla pulsada. .mouseDown() Se ha pulsado un botón del ratón. Capítulo 11: Programación Windows con Java. ratón y foco. .mouseMove() El ratón se ha movido sobre el componente. Normalmente debe especializarse y hay que reescribir su método paint() para que haga algo útil.Programación en Java. se tienen los siguientes métodos. ----AA---.mouseExit() El ratón estaba sobre el componente y ahora no. Este mensaje se envía al componente sobre el que ocurrió el evento mouseDown().mouseUp() Se ha liberado un botón pulsado del ratón. .gotFocus() El foco pasa a otro componente dentro del mismo contenedor. ----AA---. y que captura eventos. Canvas * Además de action() que recibe los eventos usuales.2005 -30- Eventos de teclado. . . * En el siguiente ejemplo. heredaremos de Canvas que es un área de pantalla rectangular en la que se puede dibujar. Cursos de Verano de Málaga . definidos en la clase base Component: -keyDown() Se ha pulsado una tecla y se mantiene pulsada. . .lostFocus() El componente deja de tener el foco.mouseEnter() El ratón ha pasado a estar sobre el componente.

width.get("gotFocus").height)/2.setText(evt.h. super. t.setText(evt. int height = fm. g.getLeading(). t.width . } public boolean mouseDown(Event evt. return true. } public boolean lostFocus(Event evt. MyButton(AutoEvent parent. String label) { this.setText(evt.stringWidth(label).*.height .h.fillRoundRect(0. rnd.setText(evt.int x. return true. Color color.width)/2. int key) { TextField t = (TextField)parent. int leading = fm. ratón.h. String label. return true.toString()). } public boolean keyUp(Event evt. return true.white). FontMetrics fm = g.getAscent(). return true.h.width.h. Canvas //: AutoEvent. } public void paint(Graphics g) { g.height.setText(evt.setColor(Color.get("lostFocus"). Color color.color = color.get("mouseDown"). g. verMargin + ascent + leading).h. int ascent = fm.Programación en Java.int x.int y) { TextField t = (TextField)parent.toString()). t.requestFocus().int y) { TextField t = (TextField)parent. g.util.*.height. size(). int horizMargin = (size(). this. int key) { TextField t = (TextField)parent.setColor(color).setText(evt.int y) { TextField t = (TextField)parent.black).int y) { TextField t = (TextField)parent.get("keyDown").get("mouseEnter"). t. import java. return true. S G R Capítulo 11: Programación Windows con Java.int x.toString()). int width = fm. } public boolean mouseExit(Event evt. class MyButton extends Canvas { AutoEvent parent. Cursos de Verano de Málaga . } public boolean mouseDrag(Event evt. g.getHeight(). } public boolean keyDown(Event evt. int verMargin = (size(). int rnd = 30.getFontMetrics().label = label. Object w) { TextField t = (TextField)parent.toString()). rnd).toString()).toString()). size(). size().int x. rnd.h.drawString(label. 0.setText(evt. this.toString()). teclado. } public boolean gotFocus(Event evt. } public boolean mouseEnter(Event evt.toString()). t. . t.get("mouseDrag"). g.setText(evt.h.drawRoundRect(0.awt. Object w) { TextField t = (TextField)parent.get("keyUp").get("mouseExit"). 0. t. t.setColor(Color. rnd).2005 -31- Ejemplo: foco.java // Alternatives to action() import java.parent = parent. return true. horizMargin. return true. size().

t. f.target == this) { System.length. i < event.setSize(300.int x. } add(b1). } } public class AutoEvent extends Frame { Hashtable h = new Hashtable(). .int x.show().get("mouseMove").WINDOW_DESTROY && e.length+1. } } * En este ejemplo se observa lo fácil que es crear nuestros propios componentes a partir de un Canvas. } public static void main(String[] args) { AutoEvent f = new AutoEvent().setText(evt. "test2"). return true. t. Label. System. return true.get("mouseUp"). "test1").put(event[i].handleEvent(e). b2 = new MyButton(this. "mouseDown".setEditable(false). add(b2).2005 } public boolean mouseMove(Event evt. Cursos de Verano de Málaga . } public boolean mouseUp(Event evt. add(new Label(event[i]. "mouseExit" }. Capítulo 11: Programación Windows con Java. t. f.Programación en Java.toString()). "mouseUp".int y) { TextField t = (TextField)parent. t). } return super."). Color.2)). "keyUp". for(int i = 0.exit(0).int y) { TextField t = (TextField)parent.toString()).CENTER)). "mouseMove". public AutoEvent() { -32setLayout(new GridLayout(event.id == Event.out. add(t). "lostFocus".red. "mouseDrag". String[] event = { "keyDown". h.setText(evt. MyButton b1 = new MyButton(this.println("Frame eliminado. } public boolean handleEvent(Event e) { if (e. i++) { TextField t = new TextField(). "gotFocus".blue. Color.h. "mouseEnter".h. 200).

drawLine(x1. int y) { if(state == ToeDialog.turn == ToeDialog. y1+high/2). int x. g. y1 + high.1. } else .turn. x1 + wide. sino que se llama a dispose() para que libere los recursos.width .parent = parent. ToeDialog parent. int x2 = size(). parent. sino que se visualiza directamente con show(). y. y1.BLANK. pero que aparece como elemento idependiente de la principal.turn= (parent.*.drawOval(x1. y1).drawRect(x1. * Además. int y2 = size(). no se sale del programa. y2). Cursos de Verano de Málaga .height . int high = y2/2. * La diferencia estriba en que no puede tener menú. un Dialog no se añade al Frame actual. g. int y1 = 0. x1 = x2/4. S G R //: ToeTest. cuando se la cierra. x1+wide/2. y1 = y2/4.OO) { g.1.java // Copyright (c) Bruce Eckel.XX ? ToeDialog. } public void paint(Graphics g) { int x1 = 0.awt. x1 + wide.drawLine(x1. y1 + high).XX) { g. x2. ToeButton(ToeDialog parent) { this. class ToeButton extends Canvas { int state = ToeDialog.XX). int wide = x2/2. } } public boolean mouseDown(Event evt.BLANK) { state = parent.OO : ToeDialog. if(state == ToeDialog. y1. 1998 // Source code file from the book "Thinking in Java" // Demonstration of dialog boxes // and creating your own components import java. } if(state == ToeDialog.2005 -33- Dialog * Un diálogo es lo mismo que una ventana. Capítulo 11: Programación Windows con Java.Programación en Java. evidentemente. y1.

WINDOW_DESTROY) dispose().equals("go")) { Dialog d = new ToeDialog( this.add(cols). f. } } public class ToeTest extends Frame { TextField rows = new TextField("3").show(). Cursos de Verano de Málaga .resize(200. p. false).id == Event. int w.exit(0).show(). h)). d. else return super. Integer. setLayout(new GridLayout(w. return true. p.handleEvent(evt). Integer. p).parseInt(rows. Object arg) { if(arg. int turn = XX. for(int i = 0. } public boolean handleEvent(Event evt) { if(evt.parseInt(cols. } public boolean handleEvent(Event evt) { if(evt. return true. i++) add(new ToeButton(this)). return true.id == Event. public ToeTest() { setTitle("Toe Test"). } else return super. -34Panel p = new Panel(). repaint(). } public boolean action(Event evt. h * 50).WINDOW_DESTROY) System.add(new Label("Rows". int h) { super(parent. p. } public static void main(String[] args) { Frame f = new ToeTest(). "The game itself".XX). static final int XX = 1. } } Capítulo 11: Programación Windows con Java. arg). f. else return super.handleEvent(evt).100). p. static final int OO = 2.OO : ToeDialog. // Start with x's turn public ToeDialog(Frame parent.action(evt. return true.add(new Label("Columns". TextField cols = new TextField("3"). Label.add(rows).2005 state = (state == ToeDialog.CENTER)).getText())).CENTER)). i < w * h.2)). new Button("go")).setLayout(new GridLayout(2.getText()). Label. . p. resize(w * 50.XX ? ToeDialog. add("North".Programación en Java. } } class ToeDialog extends Dialog { // w = number of cells wide // h = number of cells high static final int BLANK = 0. add("South".

filename.awt. . } public boolean action(Event evt.getDirectory()).handleEvent(evt). public class FileDialogTest extends Frame { TextField filename = new TextField(). return true.setText(d. El siguiente ejemplo ilustra su utilización. directory.add(save). String saveFile. add("North". Object arg) { if(evt.setText(""). p).setLayout(new FlowLayout()).setLayout(new GridLayout(2. } } else return super. add("South".setFile("*. f.setText(saveFile).equals(save)) { FileDialog d = new FileDialog(this. Panel p = new Panel(). d.exit(0). // Filename filter d.id == Event. p).2005 -35- FileDialog * Por su enorme utilidad hay un tipo especial de diálogo que sirve para abrir y guardar ficheros. } else { filename.getFile()) != null) { filename. if((saveFile = d.target. } public boolean handleEvent(Event evt) { if(evt. else return super. d.setText("You pressed cancel"). defaults to open file: FileDialog d = new FileDialog(this. f.equals(open)) { // Two arguments. p. arg). return true. Cursos de Verano de Málaga .add(directory). p.setText(d. TextField directory = new TextField().setText(""). Button save = new Button("Save")."). directory.getFile()) != null) { filename.Programación en Java.*. d. p = new Panel().show(). p. //: FileDialogTest. directory.getDirectory()). "What file do you want to save?". d.setFile("*.add(filename).action(evt. Button open = new Button("Open"). "What file do you want to open?"). 1998 // Source code file from the book "Thinking in Java" // Demonstration of File dialog boxes import java. if((openFile = d. directory. public FileDialogTest() { setTitle("File Dialog Test"). } else { filename. } } else if(evt.1)). } } S G R Capítulo 11: Programación Windows con Java.WINDOW_DESTROY) System.setEditable(false).setText("You pressed cancel").SAVE). FileDialog. String openFile.setDirectory("."). directory.java // Copyright (c) Bruce Eckel.setText(openFile). p.show(). p.show().110). p.java"). // Current directory d. } public static void main(String[] args) { Frame f = new FileDialogTest().java").setDirectory(".add(open).setEditable(false).target.resize(250.

Programación en Java. Cursos de Verano de Málaga - 2005

-36-

Java 1.1
* Java 1.1 cambia radicalmente la forma de capturar los eventos. * En Java 1.1 cada componente se mete en una lista de objetos a la escucha de un tipo de evento. Cuando un evento tal se produce sobre dicho componente se llama a otro objeto asociado que tiene un método para cada evento concreto del tipo que queremos controlar. * Todas las listas de tipos de eventos acaban en Listener, y empiezan por el tipo de evento que quiere controlar: Tipo evento Action Adjustment Component Container Focus Key Mouse Situaciones que acepta Las que acepta action(). Las que se hacen sobre barras de desplazamiento. Ocultación y redimensionamiento de componentes. Adición y eliminación de componentes. Toma y pérdida del foco. Eventos sobre teclas. Todos los eventos de ratón excepto arrastrar y mover. Todos los eventos relacionados con ventanas, excepto los de Component. Todo lo que tenga que ver con selección de elementos de una lista, o del tipo sí/no. Si se ha cambiado un texto o no.

MouseMotion Arrastrar y mover el ratón. Window Item Text

Capítulo 11: Programación Windows con Java.

Programación en Java. Cursos de Verano de Málaga - 2005

-37-

Eventos en Java 1.1
* Un componente se añade a una lista de oyentes de eventos con addXXXListener(), donde XXX es una de las listas anteriores. * Un componente se elimina de una lista de oyentes con removeXXXListener(). * Cuando se añade un componente a una lista de oyentes, se debe indicar un objeto que empezará a ejecutarse cuando se produzca es eevento sobre el objeto oyente. * Ese objeto ejecutor, debe implementar la interfaz XXXListener, y debe poseer métodos que se ejecutan cuando se produce cada evento concreto.

S G * Cada método recibe siempre un evento del tipo XXXEvent, cuyas características hay que R mirar en la documentación.
* Los eventos que controla exactamente cada XXXListener son:
interfaz Listener ActionListener AdjustmentListener ComponentListener Métodos de que dispone actionPerformed() adjustmentValueChange() componentHidden() componentShown() componentMoved() componentResized() componentAdded() componentRemoved()

ContainerListener

Capítulo 11: Programación Windows con Java.

Programación en Java. Cursos de Verano de Málaga - 2005

-38-

interfaz Listener FocusListener KeyListener

Métodos de que dispone focusGained() focusLost() keyPressed() keyReleased() keyTyped() mouseClicked() mouseEntered() mouseExited() mousePressed() mouseReleased() mouseDragged() mouseMoved() windowOpened() windowClosing() windowClosed() windowActivated() windowDeactivated() windowIconified() windowDeiconified() ItemStateChanged() textValueChanged()

MouseListener

mouseMotionListener WindowListener

ItemListener TextListener

* Como puede observarse, hay interfaces que poseen más de un método, con lo que los objetos ejecutores deben implementar todos esos métodos. * Para evitarlo, cada Listener con más de un método tiene una clase asociada con todos esos métodos ya escritos por defecto. Así, en lugar de implementar la interfaz, se puede extender el Adapter asociado y reescribir sólo los métodos que interesen. * Se dispone de los siguientes Adapter: ComponentAdapter, ContainerAdapter, FocusAdapter, KeyAdapter, MouseAdapter, MouseMotionAdapter y WindowAdapter.
Capítulo 11: Programación Windows con Java.

Programación en Java. Cursos de Verano de Málaga - 2005

-39-

Eventos soportados
* Los tipos de eventos soportados por cada componente son los siguientes:
Componente Adjustable Applet Button Canvas Checkbox CheckboxMenuItem Choice Component Container Dialog FileDialog Frame Label List Tipos de eventos soportados AdjustmentEvent ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent ActionEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent FocusEvent, KeyEvent, MouseEvent, ComponentEvent ItemEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent ActionEvent, ItemEvent ItemEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent FocusEvent, KeyEvent, MouseEvent, ComponentEvent ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent FocusEvent, KeyEvent, MouseEvent, ComponentEvent ActionEvent, ItemEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent

S G R

Capítulo 11: Programación Windows con Java.

Programación en Java. Cursos de Verano de Málaga - 2005

-40-

Componente Menu MenuItem Panel PopupMenu ScrollBar ScrollPane TextArea TextComponent TextField Window

Tipos de eventos soportados ActionEvent ActionEvent ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent ActionEvent AdjustmentEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent TextEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent TextEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent ActionEvent, TextEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent

* Para que estos nuevos tipos de eventos sean reconocidos, es necesario hacer un import de java.awt.event.*.

Capítulo 11: Programación Windows con Java.

Cursos de Verano de Málaga .2005 -41- Ejemplo de un botón //: Button2New.setText("Boton 1. // Must add this public class Button2New extends Frame { Button b1 = new Button("Button 1").addWindowListener(new WL()).awt. b2. . Capítulo 11: Programación Windows con Java."). TextField t = new TextField(15).CENTER.event.Programación en Java. add(t). 200). f. } } class B2 implements ActionListener { public void actionPerformed(ActionEvent e) { t.setSize(300. import java. } } public static void main(String[] args) { Button2New f = new Button2New(). } } S G R * Nótese que la clase WL es estática para que pueda ser usada dentro del main(). setLayout(new FlowLayout(FlowLayout. b2 = new Button("Button 2").*. add(b1).show().java // Capturing button presses import java. } } static class WL extends WindowAdapter { public void windowClosing(WindowEvent e) { System.addActionListener(new B1()).exit(0).setText("Boton 2."). add(b2). public Button2New() { b1. que es un método estático. f. f.*.awt. 20)).addActionListener(new B2()). } class B1 implements ActionListener { public void actionPerformed(ActionEvent e) { t. 20.

} } ).addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { t.awt. 20. public Button2New() { b1. // Must add this public class Button2New extends Frame { Button b1 = new Button("Button 1"). f.show(). 20)). } public static void main(String[] args) { Button2New f = new Button2New().Programación en Java.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { t. add(b2). add(t). setLayout(new FlowLayout(FlowLayout.awt.exit(0). } } Capítulo 11: Programación Windows con Java. } } ). f.event.java // Capturing button presses import java. . TextField t = new TextField(15).setText("Boton 2. b2. 200). Cursos de Verano de Málaga . //: Button2New.setText("Boton 1.*. f. import java.CENTER. add(b1). b2 = new Button("Button 2").addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.setSize(300.").").*.2005 -42- Ejemplo de un botón * El ejemplo anterior se puede simplificar haciendo uso de clases internas. } } ).

Añadirle un main() que lo único que hace es crear un Frame al que le añade el applet. } } // To close the application: static class WL extends WindowAdapter { public void windowClosing(WindowEvent e) { System. add(b1). aFrame. } class B1 implements ActionListener { public void actionPerformed(ActionEvent e) { t.awt.CENTER).applet.awt. basta con: .Programación en Java.event.init(). TextField t = new TextField(20). 1998 // Source code file from the book "Thinking in Java" // An application and an applet import java.exit(0).java // Copyright (c) Bruce Eckel. public class Button2NewB extends Applet { Button b1 = new Button("Button 1"). aFrame.*.setText("Button 1"). //: Button2NewB. applet. aFrame.*. . import java. public void init() { b1.setVisible(true).addActionListener(new B1()). } } S G R Capítulo 11: Programación Windows con Java. b2 = new Button("Button 2").addWindowListener(new WL()).start(). b2. Cursos de Verano de Málaga . add(b2). Frame aFrame = new Frame("Button2NewB"). add(t). BorderLayout. } } class B2 implements ActionListener { public void actionPerformed(ActionEvent e) { t.setText("Button 2"). .*. applet.200). // Must add this import java.addActionListener(new B2()).2005 -43- Aplicaciones y applets todo en uno * Para hacer que una misma aplicación pueda funcionar tanto como applet como como aplicación independiente. } } // A main() for the application: public static void main(String[] args) { Button2NewB applet = new Button2NewB().Crear el applet como siempre. aFrame.setSize(300.add(applet.

2005 -44- Java Swing * Swing es una nueva librería que aparece con Java 1. * Vamos a echar un vistazo general a algunas de las cosas nuevas que incorpora Swing.setV(valor).getV(). es la posibilidad de que nos salga una etiquetita cuando el ratón está un cierto tiempo sobre un componente. * Swing es una enorme y compleja librería. * La más simple de todas ellas.0.1.Programación en Java. con la diferencia de que a los nombres de las clases les antepone la letra J para evitar confusiones. y no el de Java 1. Cursos de Verano de Málaga . se hace o. Swing posee la práctica totalidad de componentes que se echan en falta hasta ahora. * Una característica de Swing es la homogeneidad en los nombres que emplea. Para asignar una propiedad V al objeto O. Capítulo 11: Programación Windows con Java. * Como introducción a Swing podemos decir que posee todos los elementos que hemos visto hasta ahora. Cualquier cosa que herede de Jcomponent tiene el método setToolTipText(String). que pretende reemplazar a la AWT utilizada hasta ahora. Para averiguar el valor de dicha propiedad se hace o.2. * Swing utiliza sólo el formato de eventos de Java 1. al que se le pasa la etiquetita a visualizar. .

*. MatteBorder.Color.CENTER). } public static void main(String args[]) { Show.*.inFrame(new Borders(). import java. Los bordes heredan de AbstractBorder. EmptyBorder.setBorder(b).border.java // Copyright (c) Bruce Eckel.30.awt. vamos a hacer uso de una clase Show. que posee un método estático al que se le pasa un Jpanel y se encarga de visualizarlo dentro de un Frame.setLayout(new BorderLayout()). 1998 // Source code file from the book "Thinking in Java" // Different Swing borders package c13.green))). .toString(). Capítulo 11: Programación Windows con Java. JLabel.30. } public Borders() { setLayout(new GridLayout(2. add(showBorder(new CompoundBorder( new EtchedBorder().awt.RAISED))).substring(nm. return jp. Cursos de Verano de Málaga .*. } } S G R * En esta y sucesivas clases.swing.swing.*. jp. new LineBorder(Color.lastIndexOf('. 300).awt.red)))). jp.blue))).getClass().event.Programación en Java.swing.CENTER).awt. EtchedBorder. add(showBorder(new EtchedBorder())). * Los bordes disponibles son BevelBorder.LOWERED))).5. import java. import java. add(showBorder(new TitledBorder("Title"))). BorderLayout. import java. jp. String nm = b. public class Borders extends JPanel { static JPanel showBorder(Border b) { JPanel jp = new JPanel(). SoftBevelBorder y TitledBorder. add(showBorder( new BevelBorder(BevelBorder. //: Borders. Es posible mezclar varios bordes con CompoundBorder. add(showBorder(new LineBorder(Color. 500. add(showBorder( new MatteBorder(5. add(showBorder( new SoftBevelBorder(BevelBorder.add(new JLabel(nm. LineBorder.4)).2005 -45- Bordes * Jcomponent tiene un método llamado setBorder() que permite colocar bordes a cualquier componente. nm = nm.') + 1).

Capítulo 11: Programación Windows con Java. y por tanto. . . . En el ejemplo puede verse su utilización. pueden poseer bordes. Igual que Checkbox.BasicArrowButton. .JcheckBox.Programación en Java. Se les puede poner la flechita en dirección a cualquier punto cardinal.Jbutton. Son botones que tienen una flechita dibujada.JradioButton. . Cursos de Verano de Málaga . entre otras. Igual que Button. como son: .JtoggleButton.2005 -46- Botones * Swing dispone de una enorme cantidad de nuevos botones. Botón que se queda pulsado. que son contadores rotatorios en formato numérico. * En el ejemplo que sigue también se ilustra el uso de Spinner y StringSpinner. Igual que CheckboxGroup con un solo botón. * Una diferencia entre estos botones y los que ya hemos visto es. y en formato cadena respectivamente. que heredan de Jcomponent.

Cursos de Verano de Málaga .plaf. public class Buttons extends JPanel { JButton jb = new JButton("JButton").addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ stringSpin.setBorder( new TitledBorder("StringSpinner")).SOUTH). down = new BasicArrowButton( BasicArrowButton. add(new JToggleButton("JToggleButton")).swing. right. ""). add(jp). import java. jp = new JPanel().setBorder(new TitledBorder("Spinner")). jp. public Buttons() { add(jb).1). 1998 // Source code file from the book "Thinking in Java" // Various Swing buttons package c13. import java.setValue( stringSpin. import java.swing. jp. add(new JCheckBox("JCheckBox")).awt. } } S G R Capítulo 11: Programación Windows con Java. left.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ spin.add(spin).1).*.awt. import java.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ spin. "green". "blue". } }).awt.Programación en Java.add(down). right = new BasicArrowButton( BasicArrowButton. jp.event.setValue( stringSpin.*. JPanel jp = new JPanel(). jp. jp. add(jp).awt. 300.*.add(up).basic.border. up.getValue() + 1).*.getValue() + 1). .add(right). "yellow" }). jp. StringSpinner stringSpin = new StringSpinner(3. jp. } }). BasicArrowButton up = new BasicArrowButton( BasicArrowButton.java // Copyright (c) Bruce Eckel.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ stringSpin.getValue() . add(new JRadioButton("JRadioButton")).add(stringSpin). import java. "".swing. } }).inFrame(new Buttons().NORTH). } public static void main(String args[]) { Show.swing. down.awt. left = new BasicArrowButton( BasicArrowButton. Spinner spin = new Spinner(47.WEST).*.setValue(spin.setValue(spin.add(left). jp.EAST). } }).getValue() .2005 -47- Botones //: Buttons. 200). new String[] { "red".

.El botón está desactivado.Programación en Java. con setVerticalAligment() y setHorizontalAlignment().No se hace nada con el botón. * Es posible hacer que los iconos salgan en distintas posiciones del botón en el que se integra. . Se usará uno u otro icono dependiendo de la acción que se haga sobre el botón asociado. . Capítulo 11: Programación Windows con Java.2005 -48- Iconos * Es posible incluir un icono dentro cualquier cosa que herede de AbstractButton. Cursos de Verano de Málaga .El ratón se desplaza sobre el botón. * Se pueden tener distintos iconos para un mismo componente. Las acciones son: . se crea un ImageIcon pasándole como parámetro el nombre del fichero . * Para ello. .El botón está presionado. Para ello se emplean las clases Icon e ImageIcon.gif a recoger. e ImageIcon devuelve un Icon que ya podemos manejar.

setVerticalAlignment(JButton.setEnabled(false).setRolloverIcon(faces[1]). } }). public class Faces extends JPanel { static Icon[] faces = { new ImageIcon("face0.setRolloverEnabled(true).awt. } else { jb. jb.Programación en Java.LEFT). public Faces() { jb. } } S G R Capítulo 11: Programación Windows con Java. jb2.setEnabled(true).setDisabledIcon(faces[4]). jb.setHorizontalAlignment(JButton.gif").awt. } } }). JButton jb = new JButton("JButton". 1998 // Source code file from the book "Thinking in Java" // Icon behavior in JButtons package c13. mad = false. 200).inFrame(new Faces(). add(jb). jb.gif"). faces[3]). add(jb2).gif").*. Cursos de Verano de Málaga .TOP).gif"). new ImageIcon("face4. import java.setIcon(faces[3]). } public static void main(String args[]) { Show.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ if(jb.*. new ImageIcon("face2.swing. jb.*. }. .event. } else { jb.isEnabled()) { jb. jb. boolean mad = false. jb2 = new JButton("Disable").awt. import java.java // Copyright (c) Bruce Eckel.setPressedIcon(faces[2]).gif").swing.2005 -49- Iconos //: Faces.setText("Enable"). jb2. jb2.setIcon(faces[0]).addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ if(mad) { jb. 300.setText("Disable"). } jb. new ImageIcon("face3.setToolTipText("Yow!"). import java. mad = true. jb. new ImageIcon("face1.

Capítulo 11: Programación Windows con Java.getContentPane(). frame.swing. puede ser algo así: //: Show. int height) { String title = jp. Cursos de Verano de Málaga . la clase Show que se pedía para visualizar todos estos ejemplos. // Remove the word "class": if(title.2005 -50- Visualización de ejemplos * Por último. JFrame frame = new JFrame(title).*.*.CENTER).*. public class Show { public static void inFrame(JPanel jp.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e){ System.Programación en Java.setVisible(true).setSize(width.indexOf("class") != -1) title = title. .getContentPane(). import java. frame.setLayout().getClass(). import java.add(jp.awt.awt. } } * Cuando se trabaja con Swing. BorderLayout. 1998 // Source code file from the book "Thinking in Java" // Tool for displaying Swing demos package c13.setLayout(). no es posible hacer frame.exit(0).java // Copyright (c) Bruce Eckel. int width.swing.awt. lo cual se consigue con frame. height). import java. } }). en su lugar hay que trabajar con la parte del Frame destinada a contener cosas.substring(6). frame.toString(). frame.event.

Java dispone de JDBC (Java DataBase Connectivity). tal como se haya declarado en el administrador de ODBC de la máquina en la que ejecuta el programa Java. * Para abrir una base de datos hay que crear un URL de base de datos (URL: Uniform Resource Locator). tendremos un R objeto driver de cada uno de ellos. * De esta forma. si nos conectamos a tres bases de datos de distintos fabricantes. es la facilidad con que trabaja con los recursos de Internet.El identificador de la base de datos. En nuestro caso emplearemos jdbc:odbc:prueba1. así como del estándar SQL-92 para efectuar los accesos a la base de datos.Que estamos usando JDBC: "jdbc". .2005 -51- JDBC * Una de las características más versátiles de Java. * Para ello. Así.Programación en Java. Cursos de Verano de Málaga . que indique: . S * Para permitir la independencia. JDBC proporciona un gestor de drivers. Capítulo 11: Programación Windows con Java. y en concreto con las bases de datos a disposición pública con ODBC. o nombre del mecanismo de conexión que se está utilizando: "odbc". JDBC es independiente de la plataforma concreta en que se encuentra la base de datos. .El subprotocolo. . que mantiene en todo momento los objetos drivers G que el programa necesite para funcionar.

los pasos a seguir para efectuar la conexión son los siguientes: 1.getBoolean(nombreDeCampo) r.Cargar el driver que permite la conexión con bases de datos de ODBC: Class. 3.odbc.getTime(nombreDeCampo) */ } s.. Esto es porpio de cada plataforma..Recorrer el ResultSet para inspeccionar todas las tuplas seleccionadas: while(r..forName("sun.getShort(nombreDeCampo) r.Ejecutar la sentencia SQL y guardar los resultados en un ResultSet: ResultSet r =s..Crear la sentencia SQL: Statement s = c.getLong(nombreDeCampo) r.executeQuery(textoDeLaSentencia).createStatement().getDouble(nombreDeCampo) r. 4.getDate(nombreDeCampo) r.Programación en Java.getConnection(dbUrl. Además hay que meter en un String el texto de la consulta SQL.JdbcOdbcDriver").getString(nombreDeCampo) r.Efectuar la conexión: Connection c = DriverManager... // Also closes ResultSet Capítulo 11: Programación Windows con Java. 6.close(). En Windows se hace a través de administrador de ODBC. user.Configurar la base de datos en DSN del sistema en ODBC.getInt(nombreDeCampo) r. . que representa a la base de datos. 2.getFloat(nombreDeCampo) r. 5. Cursos de Verano de Málaga .jdbc. que retorna un objeto Connection.2005 -52- JDBC * Una vez que disponemos del URL en cuestión.next()) { /* Las tuplas se recogen con: r. password).

. " + r. while(r. String password = "".println( r.sql.Programación en Java.executeQuery( "SELECT Nombre. } s.getString("Nombre") + ". Cursos de Verano de Málaga . public class Lookup { public static void main(String[] args) { String dbUrl = "jdbc:odbc:prueba1". // Also closes ResultSet } catch(Exception e) { e. Statement s = c. NIF " + "FROM Clientes " + "WHERE " + "(NIF > '3000') " + "ORDER BY Apellidos"). try { // Load the driver (registers itself) Class.java // Looks up email addresses in a // local database using JDBC import java.2005 -53- Ejemplo de JDBC //: Lookup.getString("aPELLIDOS") + ": " + r. String user = "".*. } } } S G R Capítulo 11: Programación Windows con Java. Apellidos.printStackTrace().out.JdbcOdbcDriver").getString("NIF") ).forName( "sun. password).createStatement().close().jdbc. // SQL code: ResultSet r = s.next()) { // Capitalization doesn't matter: System.odbc.getConnection( dbUrl. Connection c = DriverManager. user.

.Socket. * A este respecto hay dos clases fundamentales que intervienen aquí. . sino también el puerto. Es una clase que se dedica a escuchar por la red (con accept()) a ver si alguien se quiere poner en contacto con ella. + Una vez que cada uno tiene su Socket.Programación en Java.2005 -54- Comunicación vía Sockets * Vamos a ver cómo dos ordenadores pueden comunicarse vía sockets. no sólo especifica nuestra máquina. + El cliente crea un Socket para ponerse en contacto con un servidor. cada ServerSocket tiene asignado un puerto. se utiliza getInputStream y getOutputStream para establecer la comunicación. . + Cuando el ServerSocket se da cuenta de que alguien se quiere comunicar con él. crea un Socket en el servidor de manera que ya puede empezar la comunicación. + El servidor crea un ServerSocket para escuchar por la red. * Se llama socket al objeto que cada interlocutor crear para gestionar la conexión con el otro. Capítulo 11: Programación Windows con Java. de forma que cuando alguien se quiere conectar a nosotros.ServerSocket. Es el gestor de la conexión. * Dado que unamisma máquina puede tener muchos programas servidores. Cursos de Verano de Málaga .

} // Always close the two sockets.out.2005 -55- Servidor //: JabberServer.Programación en Java.*. Capítulo 11: Programación Windows con Java.out.println( "Connection accepted: "+ socket). BufferedReader in = new BufferedReader( new InputStreamReader( socket.getOutputStream())). * No debemos olvidar nunca cerra tanto el Socket como el ServerSocket.close().. } finally { System. socket.equals("END")) break. // Output is automatically flushed // by PrintWriter: PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter( socket. try { // Blocks until a connection occurs: Socket socket = s. while (true) { String str = in.net. import java. System. comento en el que devuelve el Socket correspondiente..close(). out. } } finally { s. try { System.true). ."). System.java // Copyright (c) Bruce Eckel.println("closing. public static void main(String[] args) throws IOException { ServerSocket s = new ServerSocket(PORT).getInputStream())). if (str. public class JabberServer { // Choose a port outside of the range 1-1024: public static final int PORT = 8080.out.println("Started: " + s).println("Echoing: " + str). } } } S G R * Cuando el ServerSocket hace el accept() se queda dormido hasta que recibe una petición de conexión.. import java.accept().println(str).readLine(). que vacía el buffer automáticamente (flush) tras cada retorno de carro.*.out. * Se ha hecho uso del estrato PrintWriter. 1998 // Source code file from the book "Thinking in Java" // Very simple server that just // echoes whatever the client sends.io.. Cursos de Verano de Málaga .

println("END").Programación en Java. // Alternatively. Socket socket = new Socket(addr. i ++) { out.PORT). 1998 // Source code file from the book "Thinking in Java" // Very simple client that just sends // lines to the server and reads lines // that the server sends.net. en cuya construcción se indican la máquina y el puerto de conexión. } out. String str = in. // Output is automatically flushed // by PrintWriter: PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter( socket.1").*.println("socket = " + socket).0. Capítulo 11: Programación Windows con Java. Para especificar la máquina de conexión se utiliza un objeto de tipo InetAddress.println(str).getByName(null). JabberServer. public class JabberClient { public static void main(String[] args) throws IOException { // Passing null to getByName() produces the // special "Local Loopback" IP address.out. System. } } } * Para efectuar la conexión.getInputStream())).true). System. BufferedReader in = new BufferedReader( new InputStreamReader( socket.io. } finally { System.0. you can use // the address or name: // InetAddress addr = // InetAddress.java // Copyright (c) Bruce Eckel. for // testing on one machine w/o a network: InetAddress addr = InetAddress.getByName("127. import java. import java.*. // InetAddress addr = // InetAddress.close()..out. . socket.out.println("closing. al que se le pasa la dirección internet como String.out. Cursos de Verano de Málaga . // Guard everything in a try-finally to make // sure that the socket is closed: try { System.getOutputStream()))."). for(int i = 0.readLine().getByName("localhost")..println("addr = " + addr).2005 -56- Cliente //: JabberClient. basta con crear un Socket.println("howdy " + i). i < 10. * Para coger una máquina basta con llamar al método estático getByName().

} } } S G R * Cuando se cierra la conexión el thread desaparece. true). // If any of the above calls throw an // exception. out.close(). try { new ServeOneJabber(socket). import java. start(). } catch (IOException e) { } finally { try { socket. * Los try-catch sirven para asegurarse de que los sockets se cierran.println("closing. } System. close the socket.close().java // Copyright (c) Bruce Eckel.close().Programación en Java.getOutputStream())). public ServeOneJabber(Socket s) throws IOException { socket = s.getInputStream())). private PrintWriter out. System. public static void main(String[] args) throws IOException { ServerSocket s = new ServerSocket(PORT). } } } finally { s.").. Capítulo 11: Programación Windows con Java.accept().2005 -57- Servir a muchos clientes //: MultiJabberServer. Cursos de Verano de Málaga .out.out. import java.equals("END")) break. 1998 // Source code file from the book "Thinking in Java" // A server that uses multithreading to handle // any number of clients.*.println("Server Started"). the caller is responsible for // closing the socket. } catch(IOException e) {} } } } public class MultiJabberServer { static final int PORT = 8080. // otherwise the thread will close it: socket. if (str.println(str).*.. System. in = new BufferedReader( new InputStreamReader( socket. . Otherwise the thread // will close it.out. private BufferedReader in. try { while(true) { // Blocks until a connection occurs: Socket socket = s. } catch(IOException e) { // If it fails.io. // Calls run() } public void run() { try { while (true) { String str = in.readLine(). // Enable auto-flush: out = new PrintWriter( new BufferedWriter( new OutputStreamWriter( socket. class ServeOneJabber extends Thread { private Socket socket.net.println("Echoing: " + str).

Applets y threads * Un applet puede comunicarse con el ordenador-servidor del que procede.2005 -58- Acceso por Internet a Bases de Datos.Datos textuales que el applet directamente. * El servicio del thread consiste en enviar los datos requeridos al applet cliente. * El servidor puede conectarse a una base de datos y suministrar información al applet.El nombre de una página . * Los datos enviados pueden ser: . Es una forma de conectar un ordenador cliente con una base de datos situada en el servidor. Capítulo 11: Programación Windows con Java. .Programación en Java. * El servidor debe crear un thread por cada petición que reciba. . y destruirse cuando acabe su servicio. Cursos de Verano de Málaga . y en la que coloca los datos en forma de tabla. Cada thread debe servir a un cliente.html que el thread crea dinámicamente.

.El applet se conecta al servidor.2005 -59- Internet. .html dinámicamente. Cursos de Verano de Málaga .El servidor crea un thread de atención. .El thread desaparece. con los datos solicitados.El applet solicita los datos al thread.html creadas dinámicamente. BB. . Capítulo 11: Programación Windows con Java.Programación en Java. .DD. * Cada cierto tiempo hay que eliminar las páginas . . y Applets * La comunicación sigue el siguiente esquema: S G R * Los pasos que se siguen son: .El applet carga la página en el navegador.El thread le dice al applet el nombre de la página.El thread crea una página . .

Cada línea comienza con <TR>. Capítulo 11: Programación Windows con Java. . Cursos de Verano de Málaga . * El siguiente fichero HTML: <TABLE> <TR><TH> Col1 <TH> Col2 <TH> Col3 <TR><TD> Dato11 <TD> Dato12 <TD> Dato13 <TR><TD> Dato21 <TD> Dato22 <TD> Dato23 <TR><TD> Dato31 <TD> Dato32 <TD> Dato33 </TABLE> produce la tabla: * A una tabla se le pueden especificar distintos tipos de bordes. . .Programación en Java.2005 -60- Creación de tablas en HTML * Las tablas en HTML siguen una estructura muy sencilla: .Cada dato de cada columna comienza por <TD>.Cada cabecera de cada columna comienza por <TH>. .Empiezan por <TABLE> y acaban con </TABLE>.

applet. try{ Socket s = new Socket(InetAddress.close().*.net. s. 8080).getInputStream())). true). " + t2.Programación en Java. El applet * El applet quedaría como sigue: import java.getText()).addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){alfa().getText() + " " + a.out. in = new BufferedReader(new InputStreamReader(s. out. S G R . import java. import java.es/" + nombreFichero)). } catch (IOException e){ System. else getAppletContext().showDocument(new URL("http://altamira.awt. // Forma parte del protocolo de comunicaciones.getText() + ".getText()).equals("ERROR"))) getAppletContext(). out.getByName("altamira.getOutputStream())). BufferedReader in. out. add(a).io.println("END").es").showStatus(nombreFichero). TextArea a = new TextArea().println(t1.readLine().*.*. add(b).event.DD.*. String nombreFichero = in. TextField t2 = new TextField(10). b. Cursos de Verano de Málaga . out. } } } Capítulo 11: Programación Windows con Java. add(t2). out = new PrintWriter( new BufferedWriter( new OutputStreamWriter( s. Button b = new Button("Enviar").println("SELECT "+ t1. add(t1).getText()).println("Hay algún error con la red").println(t2. import java. } public void alfa(){ PrintWriter out.*.awt. import java.2005 -61- Internet y BB. if ((nombreFichero == null) || (nombreFichero. public class ClientDB extends Applet{ TextField t1 = new TextField(10).} } ). public void init(){ setLayout(new FlowLayout()).

getInputStream())).accept().JdbcOdbcDriver").println("A la espera"). // c. import java.net.Programación en Java."). } catch (IOException e){ System. }. c = DriverManager. true). ServerSocket ss = new ServerSocket(8080).").start(). PrintWriter out. public Acceso(Socket k."). public class ServerDB{ public static void main(String args[]){ Connection c.out. } } } class Acceso extends Thread{ BufferedReader in.awt. "". s = k.jdbc. "").*. Connection c. import java.odbc.getConnection("jdbc:odbc:cursjava".close().. } catch (IOException e){ System. } } Capítulo 11: Programación Windows con Java. out = new PrintWriter( new BufferedWriter( new OutputStreamWriter( s.out.DD.2005 -62- Internet y BB. .*. Socket s = ss. try{ in = new BufferedReader( new InputStreamReader( s. Cursos de Verano de Málaga . Servidor * El servidor sería: import java. new Acceso(s.println("Error con la base de datos o con la clase del ODBC. Socket s.println("Procesando.io.out.sql. c).*. import java. System. while(true){ System. try{ Class.getOutputStream())).println("Hay algún error con la red. Connection h){ c = h. } catch (Exception e){ System.out.out.println("Hay algún error con la red al abrir el socket").forName("sun.*..

// Paso 2. Cursos de Verano de Málaga .println("</Table>"). // Sólo 10 campos. i++) fileOut.readLine().println("</html>").println("</body>").println("<th> " + campos[i]). Cancelado. PrintWriter fileOut = new PrintWriter( new BufferedOutputStream( new FileOutputStream(nombreFichero))).next()){ fileOut.out.executeQuery(sentencia)."). } fileOut. // Paso 3.out. El 11-avo es para "END".println("<tr>"). DataInputStream fileIn = new DataInputStream( new BufferedInputStream( new FileInputStream("plantilla. Escribir la cabecera. i < cont.currentTimeMillis() + ".txt"))).close().html"). for (int i = 0. fileOut. Abrir el fichero plantilla. Copiar en el fichero resultado los datos obtenidos. int cont = 0. try{ if ((in == null) || (out == null)) System. Copiar el fichero plantilla en el fichero resultado.1. i++) fileOut. S G R Capítulo 11: Programación Windows con Java.close().println("Demasiados campos. . fileOut. } out.2.println("<td> " + r. } while ((! campos[cont . fileIn. if (! campos[cont]. i < cont.readLine()) != null) fileOut.close(). fileOut. while ((entrada = fileIn.readLine(). // Paso 1. String nombreFichero = new String("file" + System.").2005 -63- public void run(){ String[] campos = new String[11]. } String sentencia = in. Escribir los datos. Statement s = c.Programación en Java. s.println(nombreFichero).getString(campos[i])). fileOut. while (r.1]. // Paso 3.createStatement(). else{ do{ campos[cont++] = in. Cancelado. // Aquí construiremos una página html nueva.println("No se inicia comunicación.equals("END")){ System. cont--. String entrada.println("<Table Border=\"0\"><tr>"). return. ResultSet r = s. // Paso 3. for (int i = 0.println(entrada).equals("END")) && (cont <= 11)).

println("ERROR").Programación en Java. try{ out. } catch (Exception ex){} } catch (IOException ex){ System.").println("Error de E/S.").2005 } catch (SQLException e){ System. Cursos de Verano de Málaga .printStackTrace(). e.out. } } } -64- Capítulo 11: Programación Windows con Java.printStackTrace().out. .println("Error en la sentencia SQL. } catch (Exception ex){ ex.

llamado servlet. Cuando el navegante pulsa el botón “Enviar”. * ES NECESARIO USAR UN SERVIDOR WEB.html es un formulario que el navegante rellena en la máquina cliente. Para que funcione correctamente es necesario colocar en el CLASSPATH al fichero servlet.2 admite esta posibilidad. y se la envía al navegador que. * La página .0). . en la máquina servidora debe ejecutarse un servidor de servlets.html y un servlet conectado a dicha página. la muestra al navegante como resultado de su consulta R a través del formulario. pero sin necesidad de tener un applet ejecutándose en el cliente. Cursos de Verano de Málaga . * Para que todo esto funcione.html y el servidor.2005 -65- Servlets * A menudo conviene establecer comunicación entre una página . colocaremos los servlets en el directorio”jswdk-1. * El servidor de servlets se arranca con startserver.Programación en Java. Capítulo 11: Programación Windows con Java. el navegador envía el contenido del formulario a un programa ubicado en la máquina servidora.0\webpages\WEBINF\servlets\”. S * El servlet crea dinámicamente una página .html (sin necesidad G de guardarla en un fichero). Java 1.jar. * El ejemplo del punto anterior también se puede desarrollar mediante una página . Usaremos el JSWDK 1.0 (Java Servlets Web Development Kit versión 1. entonces.

Esta acción es el nombre del servlet a ejecutar. Al campo se le da un nombre con name.Una etiqueta de comienzo <FORM> y otra de final </FORM>.es:8080/servlet/MiPrimerServlet method=”POST”> <BR> <BR>Introduzca un texto en el cuadro y pulse "Submit"<BR> <BR> <input type=text name=TEXTO> <BR> <BR><input type=submit><input type=reset></form> produce el formulario: Capítulo 11: Programación Windows con Java. incluyendo la URL en que se encuentra. .lcc.La etiqueta <INPUT> para definir la estructura del formulario. * El siguiente fichero HTML: <form action=http://betelgeuse. . Cursos de Verano de Málaga . Éstas pueden ser de varios tipos (type): + submit: Crea el botón para enviar el formulario. + text: Crea un campo de texto a ser relleno por el usuario navegante.2005 -66- HTML y formularios * Los formularios en HTML constan de las siguientes etiquetas: .Programación en Java.La etiqueta <FORM> lleva asociada la acción (action) que hay que realizar cuando se pulsa el botón submit. .uma. + reset: Crea el botón para borrar el contenido.

Para cada solicitud de servicio por parte de un cliente. etc.Cuando hace mucho que el objeto de ese servlet no recibe peticiones. etc.El servidor de servlets carga los servlets bajo demanda. Cursos de Verano de Málaga . el servidor creará varios threads que acceden simultáneamente a un mismo objeto servlet: usar synchronized cuando sea necesario. entonces queda en desuso y debe desaparecer de memoria: se invoca a destroy() quien debe: cerrar bases de datos. el servidor invoca a la función service del objeto anteriormente creado. . eliminar threads. .init() debe inicializar todos aquellos componentes que tengan vigencia mientras dicho objeto siga vivo: abrir bases de datos. . . Capítulo 11: Programación Windows con Java. crear threads.2005 -67- Ciclo de vida de un Servlet * Un servlet tiene un ciclo de vida similar al de un applet: .Programación en Java. S G * ¡Cuidado! Los servlets son reentrantes lo que quiere decir que R si se reciben varias peticiones a un mismo servlet.La primera vez que carga un servlet crea un objeto cuyo tipo es ese servlet e invoca a su init(). .

que permiten la comunicación con el formulario enviado: uno del tipo HttpServletRequest y otro del tipo HttpServletResponse. * Cuando el servidor invoca al servlet llama a su método service. al que se le pasa como parámetro el nombre del campo de texto cuyo contenido se desea conocer. el valor de la cadena debe ser “text/html”.html. Cursos de Verano de Málaga . se invoca el mensaje getParameter(String) de HttpServletRequest. y en el que habrá que colocar el código de lo que se quiere hacer.Programación en Java. * HttpServletResponse admite el mensaje getOutputStream() que devuelve un objeto del tipo PrintStream.2005 -68- Clases para Servlets * Todo servlet debe heredar de HttpServlet.html. * Antes de enviar datos por el canal de salida. . donde Xxx representa el método de comunicación usado en la página .html. Capítulo 11: Programación Windows con Java. quien a su vez llama al método doXxx. * Para tomar cada campo del formulario origen. hay que especificarle al navegador la naturaleza de los datos que se van a transmitir. Para las páginas . que aparecerá automáticamente en el navegador del cliente. * Las funciones doXxx() toman dos parámetros. A través de este canal escribiremos la página . Ello se hace a través del mensaje setContentType(String).

HttpServletResponse res) throws ServletException.getParameter("TEXTO"). public class MiPrimerServlet extends HttpServlet { public void doGet(HttpServletRequest req.servlet.servlet.*. * La utilización de cookies es relativamente fácil a través de la clase Cookie. out. .http.getParameterNames() devuelve un Enumeration con los parámetros pasados por el formulario. import javax.2005 -69- Ejemplo de Servlet * Un servlet que recoja los datos del formulario visto anteriormente sería: import javax. Capítulo 11: Programación Windows con Java.getRemoteAddr() devuelve la dirección TCP/IP del } cliente. import javax. res.setContentType("text/html").io. Cursos de Verano de Málaga .getOutputStream()).*.println("<p>Usted ha escrito : "+TEXTO+"</p>").*. import java. . . } S G * La clase HttpServletRequest posee diversos métodos: R .Programación en Java. IOException { PrintStream out = new PrintStream(res.getRemoteHost() devuelve el nombre del cliente.servlet.ServletException. String TEXTO = req.

* En la máquina cliente se debe disponer de la interfaz que suministra el objeto remoto.Programación en Java. a la espera de recibir mensajes.rmi.rmi.java // The PerfectTime remote interface package c15. * En la máquina remota.Si un objeto remoto se pasa como argumento. en el cliente se siguen los siguientes pasos: R . y el que manda el mensaje el cliente.*.Exception.Crear la interfaz como pública.Dicha interfaz debe extender a java.Remote. .Remote.Cada método de la interfaz puede lanzar la excepción java. * Esto permite tener objetos Java en otros ordenadores de Internet.2005 -1- Capítulo 12: RMI * RMI (Remote Method Invocation). import java. interface PerfectTimeI extends Remote { long getPerfectTime() throws RemoteException. //: PerfectTimeI. y que los ejecuten. su tipo debe ser el de la interfaz que declaramos. .ptime. el objeto debe estar vivo permanentemente. } Capítulo 12: RMI. .rmi. Cursos de Verano de Málaga . * El objeto remoto es el servidor. que reciban mensajes. . S G * Para conseguir esto.

debe implementar Serializable. * Cualquier parámetro que se le pase en un mensaje a un objeto remoto. rmiregistry debe ser capaz de encontrar las clases de los objetos que sirve. y darles un nombre con: Naming. lo que se consigue con: rmiregistry puerto desde MS-DOS. se hace unbind(). * Crear cuantas instancias se necesiten del objeto remoto. que puede elevar la excepción RemoteException. Cursos de Verano de Málaga . * El programa main() debe instalar al gestor de seguridad. * Para que lo anterior funciones. donde maquina es una cadena con la dirección IP y el nombre del objeto.2005 -2- RMI. de la forma: System.setSecurityManager(new RMISecurityManager()).Programación en Java. objeto).bind(maquina. o que éste devuelva. El servidor * La clase correspondiente en el servidor debe extender a la clase UnicastRemoteObject. Máquina puede poseer un puerto por el que se establecerá la comunicación. Para hacer que un objeto deje de estar disponible. . y objeto es un manejador al objeto remoto. el servidor debe tener funcionando en background rmiregistry. * Debe poseer obligatoriamente un constructor. e implementar la interfaz remota. Capítulo 12: RMI.

para que el cliente lo pueda utilizar necesita un representante de dicho objeto: es lo que se llama stub o proxy. (en la versión JDK 1. .El cliente se comunica con el stub. .class y nombreClase_Skeleton. S * Para generar el stub y el skeleton de la clase del objeto remoto. * Para comunicar el stub con el objeto remoto. G hay que ejecutar desde MS-DOS rmic nombreClase. Cursos de Verano de Málaga .2 no es necesario). lo que nos generará dos nuevos ficheros necesarios para la comunicación: R nombreClase_Stub.class * Los stub y skeleton también se encargan de serializar los parámetros.El skeleton se comunica con el objeto remoto.2005 -3- La comunicación * Aunque el objeto remoto resida en una máquina diferente.Programación en Java. el servidor necesita un skeleton. * La comunicación es como sigue: .El stub se comunica con el skeleton a través de la red (protocolo de transporte). Capítulo 12: RMI. .

ptime. } catch(Exception e) { e. System.rmi.*.policy del directorio jre/lib/security/.*.println("Ready to do time"). Capítulo 12: RMI. pt).rmi. } // Must implement constructor to throw RemoteException: public PerfectTime() throws RemoteException { // super().out.server. Cursos de Verano de Málaga . public class PerfectTime extends UnicastRemoteObject implements PerfectTimeI { // Implementation of the interface: public long getPerfectTime() throws RemoteException { return System. establecida por el fichero java. import java. import java. El servidor //: PerfectTime.2005 -4- RMI.java // Copyright (c) Bruce Eckel. }. añadiendo: grant { permission java.AllPermission.registry. . try { PerfectTime pt = new PerfectTime().*.2).rmi.security.printStackTrace(). Naming.net.setSecurityManager(new RMISecurityManager()).*.currentTimeMillis(). hay que modificar la política de seguridad. import java. // Called automatically } // Registration for RMI serving: public static void main(String[] args) { System.bind("//colossus:2005/PerfectTime". } } } * Para que todo funcione bien (en JDK 1.Programación en Java. 1998 // Source code file from the book "Thinking in Java" // The implementation of the PerfectTime remote object package c15. import java.

2005 -5- RMI. tiene que buscarlo en el servidor con: Naming. for(int i = 0. import java.ptime.rmi.setSecurityManager( new RMISecurityManager()). .*.*.registry.printStackTrace(). i < 10. Cursos de Verano de Málaga .Programación en Java.rmi. 1998 // Source code file from the book "Thinking in Java" // Uses remote object PerfectTime package c15. i++) System. con la única diferencia de que en vez de crearlo.println("Perfect time = " + t. //: DisplayPerfectTime. El cliente * El cliente trata los objetos temotos como si de cualquier otro objeto se tratase. } } } S G R Capítulo 12: RMI. public class DisplayPerfectTime { public static void main(String[] args) { System. lo que devuelve un Object que habrá que convertir a la interfaz que se tiene disponible en el cliente.lookup( "//colossus:2005/PerfectTime").getPerfectTime()).out. import java.lookup(maquina_y_nombreObjeto).java // Copyright (c) Bruce Eckel. try { PerfectTimeI t = (PerfectTimeI)Naming. } catch(Exception e) { e.

..2005 -6- Parámetros * El servidor debe ejecutar Naming. * Si el ordenador servidor sólo va a tener un programa (JVM) que registre objetos remotos. * Pero no todo objeto remoto tiene porqué ser registrado con un nombre. Contra este problema existe una solución alternativa: un objeto cualquiera se puede hacer remoto con el mensaje: UnicastRemoteObject. sino que el propio programa puede arrancar una instancia de rmiregistry dedicada a él sólo. no puede heredar de UnicastRemoteObject. * Esto permite que un cliente acceda a un objeto remoto a través de su nombre con Naming.exportObject( objeto ). Es posible pasar un objeto remoto como parámetro en una llamada remota a otro objeto remoto.lookup(. no es necesario ejecutar rmiregistry aparte.bind(.) para registrar el objeto en el servidor de nombres de objetos rmiregistry.. Cursos de Verano de Málaga . Esto se hace con: LocateRegistry. ..createRegistry( PUERTO ). * Si la clase del objeto que se quiere hacer remoto ya hereda de otra clase.Que herede de UnicastRemoteObject.Que existan los necesarios stub y skeleton para la comunicación. * Lo que verdaderamente convierte a un objeto en remoto es: .. * rmiregistry puede registrar objetos generados por diferentes programas java (diferentes JVM) ubicados en un mismo servidor.Programación en Java.). Capítulo 12: RMI.

import java.rmi.println( "Registry created" ).rmi. // Copyright MageLang Institute." ).start(). System.io. import java. private static RMIServer rmi. } catch ( MalformedURLException mURLe ) { System. try { rmi = new RMIServer().println( "The host computer name you have specified.println( "Timer Started" ).server.Programación en Java. } catch ( java.createRegistry( PORT ). System. UnicastRemoteObject. Cursos de Verano de Málaga . " + HOST_NAME + " does not match your real computer name. tt.out.out.println( "Internal error" + mURLe ).Date. } } // main public void registerTimeMonitor( TimeMonitor tm ) { System.*. import java.*. } catch ( RemoteException re ) { System. TimeTicker tt.UnknownHostException uhe ) { System.rmi. .util.exportObject( ((TimeServer)rmi) ). } } // class RMIServer S G R Capítulo 12: RMI.out. import java.out.LocateRegistry.setSecurityManager( new RMISecurityManager() ). System.rebind( "//" + HOST_NAME + ":" + PORT + "/" + "TimeServer".net.out. rmi ). tt = new TimeTicker( tm ).println( "Waiting for Client requests" ).out. public class RMIServer implements Remote.out.*.out. LocateRegistry. public static void main ( String[] args ) { // We need to set the security manager to the RMISecurityManager System. import java. import java.println( "Client requesting a connection" ). private static final String HOST_NAME = "betelgeuse".out.2005 -7- Retrollamadas * RMI permite que cliente y servidor puedan intercambiar sus papeles.println( "" + re ).println( "Error starting service" ). System.rmi.registry. Naming. TimeServer { private static final int PORT = 10005.*.println( "Bindings Finished" ). System.

tellMeTheTime( new Date() ). tm. public interface TimeServer extends java. } -8- * En este ejercicio. } catch ( Exception e ) { stop().Remote { public void registerTimeMonitor( TimeMonitor tm) throws RemoteException. import java. un applet va a invocar a un objeto remoto para que le diga la hora cada dos segundos.tm = tm. a su vez. otro objeto remoto. Para dicho objeto remoto el applet es.rmi. Capítulo 12: RMI. . Cursos de Verano de Málaga .Programación en Java. } public void run() { while ( true ) { try { sleep( 2000 ).2005 class TimeTicker extends Thread { private TimeMonitor tm.rmi.*. } } } } // Copyright MageLang Institute. TimeTicker( TimeMonitor tm ) { this.

appendText( d. UnicastRemoteObject.out. } Capítulo 12: RMI.out. try { ts = (TimeServer)Naming.awt.println( "Looking up TimeService at: " + serverName ).event.getHost(). public class Applet1 extends Applet implements TimeMonitor { private final static String HOST_NAME = "betelgeuse". Cursos de Verano de Málaga . String hostName = base.out.*.server. uiInit().*.Date. public void init() { super.*.init().println( "We have been registered!" ). import java. } } S G R public void tellMeTheTime( Date d ) { textArea1. System.*. } catch ( Exception e ) { System.println( "Exporting the Applet" ). import java.out. URL base = getDocumentBase().URL.exportObject( this ). .toString() + "\n" ).out.length() ) { hostName = HOST_NAME. try { System.println( "" + e ). import java.println( "" + re ).awt.rmi.rmi.2005 -9- Retrollamadas // Copyright MageLang Institute.lookup( serverName ). import java.net.*. } String serverName = "rmi://" + hostName + ":" + getParameter( "registryPort" ) + "/TimeServer" .util.registerTimeMonitor( this ). System. } catch ( RemoteException re ) { System. } ts.applet.Programación en Java. if ( 0 == hostName. import java. import java. import java. private TimeServer ts.

rmi. } // Copyright MageLang Institute. java. import java. Capítulo 12: RMI.rmi.36.*.72. textArea1 = new java.170).setText(""). public interface TimeMonitor extends java.24. resize(456.Programación en Java.awt.awt. } } ).Date. .TextArea textArea1.252. import java. add(button1).html.addActionListener ( new ActionListener() { public void actionPerformed(ActionEvent event) { textArea1.awt. } java. button1 = new java. add(textArea1).Remote { public void tellMeTheTime( Date d ) throws RemoteException.TextArea(). Cursos de Verano de Málaga .awt. } * El applet necesita un parámetro que le diga por qué puerto debe comunicarse.reshape(36. Este parámetro se le pasa en el correspondiente fichero .266). textArea1.reshape(324. button1.2005 -10- public void uiInit() { setLayout(null). button1.24).Button button1.Button("Clear").util.

FTP o similar. Esto se hace a través de la propiedad java.codebase. cuando se coloca a true hace que las clases remotas sólo se puedan cargar desde java. el siguiente programa se ejecuta con: java -Djava. con: java -Dnombre. S * La máquina servidora debe G servir HTTP. .server.rmi. * La propiedad java. que devuelve un objeto de la clase representada. Dado que devuelve un Object es necesario realizar un downcasting.class se puede cargar remotamente a través de la clase RMIClassLoader.rmi. * Es posible indicarle a Java que debe buscar los .codebase.class en una máquina diferente.class.server. Cursos de Verano de Málaga .server. que se hace igual a una URL que será la máquina servidora que contiene los .2005 -11- Descarga de clases * Un .server.useCodebaseOnly.rmi. Las propiedades se pueden especificar en el momento de ejecutar Java.server.rmi.logCalls hace que se visualicen por el dispositivo stderr los mensajes de conexión. Sun suministra la clase ClassFileServer como servidora.rmi.propiedad=valor NombreClase * Tras crear todas las clases y tener el servidor de clases.Programación en Java. nombreClase) * La clase Class admite el método newInstance(). R * La propiedad java. mediante la función estática: Class loadClass(url.codebase=http://betelgeuse:2002/ RMIClientLoader Capítulo 12: RMI.

La siguiente propiedad le puede decir tal lugar.println("After loading Client Class").rmi.out. private String clientName.io. } catch (MalformedURLException mURLe) { System.registry. import java.out.out.println("URL not specified correctly for the Client class: " + mURLe). p. // El cliente que descargamos puede incluso acceder a un objeto remoto // situado en cualquier lugar.*. import java.run.newInstance()). public RMIClientLoader() throws MalformedURLException.out. InstantiationException. private static final String HOST_NAME = "betelgeuse".*. clientName).println("RMIClientLoader. Cursos de Verano de Málaga .out.server. import java. System.rmi. clientName = "RMIClient".rmi. ((Runnable)clientClass.println("RMIClientLoader. class not found: " + cnfe).*. url = new URL(p.Properties. try { rcl = new RMIClientLoader().*. System.LocateRegistry.codebase")).out.rminode". private Properties p. System. private URL url.getProperties(). } catch (ClassNotFoundException cnfe) { System. } public static void main (String args[]) { System.getProperty("java. private Class clientClass.println("Asking for: " + url + " and " + clientName).server.setSecurityManager(new RMISecurityManager()).put("java. clientClass = RMIClassLoader.net. import java. import java.rmi. private static RMIClientLoader rcl.util. } } // main } // class RMIClientLoader Capítulo 12: RMI. "rmi://" + HOST_NAME + ":" + PORT + "/"). } catch (InstantiationException ie) { System.println("Internal error" + iae). ClassNotFoundException.Programación en Java.rmi.loadClass(url. public class RMIClientLoader { private static final int PORT = 10009.2005 -12- Descarga de clases // Copyright MageLang Institute. class could not be instantiated" + ie). } catch (IllegalAccessException iae) { System. import java.println("" + url). .out. IllegalAccessException { p = System.server.

security.policy. public synchronized void checkPropertiesAccess() {} } * Para más información.Mediante la propiedad java. La relajación suministrada por * esta clase es la mínima necesaria para que todo funcione. public synchronized void checkAccess(ThreadGroup g) {} // Loaded classes are allowed to access the system properties list. public synchronized void checkAccess(Thread t) {} // Loaded classes are allowed to manipulate thread groups.Creando un nuevo SecurityManager // Copyright MageLang Institute. consultar la clase RMISecurityManager. /** * Esta clase define una política de seguridad para aplicaciones * RMI cargadas desde un servidor. * * Los cambios con respecto al RMISecurityManager por defecto son: * * Security Check This Policy RMISecurityManager * ---------------------------------------------------------* Access to Thread Groups SÍ NO * Access to Threads SÍ NO * Create Class Loader SÍ NO * System Properties Access SÍ NO * Connections SÍ NO * */ S G R public class RMIClientBootstrapSecurityManager extends RMISecurityManager { // Loaded classes are allowed to create class loaders.Programación en Java.Mediante el fichero java. Cursos de Verano de Málaga .policy. Capítulo 12: RMI.2005 -13- Política de seguridad * La política de seguridad se puede cambiar de varias maneras: . public synchronized void checkCreateClassLoader() {} // Connections to other machines are allowed public synchronized void checkConnect(String host. . . int port) {} // Loaded classes are allowed to manipulate threads. .

Cursos de Verano de Málaga . * Para ello. lo registraba y el servidor seguía funcionando todo el tiempo. en este proceso se ven implicados: . que estará a null si el objeto aún no ha sido activado. . * Con JDK 1.Un activador. hay que activarlo en el servidor. * Cuando se envía un mensaje a un objeto dormido. y sin que el servidor funcione todo el tiempo. * El activador (uno por servidor) mantiene información entre los identificadores de activación y la información interna necesaria para la activación.2005 -14- Activación remota de objetos * Hasta ahora. el stub del cliente posee un identificador de activación y una referencia viva al objeto. para acceder un objeto remoto.Un grupo de activación en una JVM. . * Un grupo de activación (uno por JVM) recibe la petición de activar un objeto en su JVM y le devuelve al activador el objeto activado. el servidor lo creaba. .2 es posible crear un objeto remoto que se active automáticamente cuando sea necesario.Programación en Java.Una referencia de fallo (el mensaje no se ha podido ejecutar bien porque el objeto estaba dormido). Capítulo 12: RMI.

2005 -15- Protocolo de activación * El protocolo de activación: .Una referencia de fallo usa un identificador de activación y llama al activador (clase interna de RMI) para activar al objeto asociado. hay que ejecutar en background el dispensador de activaciones R rmid (RMI daemon). Cursos de Verano de Málaga . . y que contiene: > El identificador de grupo (indica la JVM en que se ejecutará el objeto). S G * Para poder utilizar el sistema de activación automático. * Para todo esto se utilizan las clases: ActivationGroup ActivationGroupID ActivationGroupDesc ActivationDesc MarshalledObject Activatable ActivationGroupDesc. > La URL donde encontrar su .CommandEnvironment Capítulo 12: RMI. > El nombre de la clase del objeto.El activador busca el descriptor de activación (que ha debido ser previamente registrado). > Datos de inicialización en formato plano (marshalled). rmiregistry debe estar activado también.class.Programación en Java. .

Cursos de Verano de Málaga . Inc.registerGroup(exampleGroup).2005 -16- Ejemplo de activación // Copyright (c) 1998.policy".exit(0). 2000 Sun Microsystems.register(desc).println("Got the stub for the ActivatableImplementation"). // Register with rmid MyRemoteInterface mri = (MyRemoteInterface)Activatable. All Rights Reserved. "\\jdk1. ace).rebind("ActivatableImplementation".out.Properties. 1999. import java. // Bind the stub to a name in the registry running on 1099 Naming. ActivationDesc desc = new ActivationDesc ("ActivatableImplementation". // Don't forget the trailing slash at the end of the URL or classes won't be found.out. location.2\\jre\\lib\\security\\java.rmi.Programación en Java.util. System. data).createGroup(agi. ActivationGroupDesc exampleGroup = new ActivationGroupDesc(props. import java.put("java.println("Exported ActivatableImplementation"). // Now explicitly create the group ActivationGroup. public class Setup { // This class registers information about the ActivatableImplementation // class with rmid and the rmiregistry public static void main(String[] args) throws Exception { System.*.CommandEnvironment ace = null. // The second argument to the ActivationDesc constructor will be used // to uniquely identify this class. 0). exampleGroup.activation. props. // The "location" String specifies a URL from where the class // definition will come when this object is requested (activated). Properties props = new Properties(). it's location is relative to the // URL-formatted String.setSecurityManager(new RMISecurityManager()). .security.policy"). mri). String location = "file:/Sergio/temp/c15/activo/". // Because of the Java 2 security model. a security policy should // be specified for the ActivationGroup VM.*. System. location. import java. System.rmi.getSystem(). } } Capítulo 12: RMI. // Create the rest of the parameters that will be passed to // the ActivationDesc constructor MarshalledObject data = null. register it // with the activation system to obtain its ID ActivationGroupID agi = ActivationGroup. ActivationGroupDesc. // Once the ActivationGroupDesc has been created.

Programación en Java. 1999. } } * El cliente que hace uso del objeto. MarshalledObject data) throws RemoteException { // Register the object with the activation system // then export it on an anonymous port super(id.newInstance during // activation. de la forma: Activatable. 0). donde id y 0 tienen el mismo sentido que la llamada al constructor de la clase padre en caso de que sí heredase.rmi.rmi.*. S G R Capítulo 12: RMI. this constructor is // called by the method ActivationInstantiator. } import java. Inc. 0). } public Object callMeRemotely() throws RemoteException { return "Perfecto".*.2005 -17- Ejemplo de activación // Copyright (c) 1998. public class ActivatableImplementation extends Activatable implements MyRemoteInterface { // The constructor for activation and export. public interface MyRemoteInterface extends Remote { public Object callMeRemotely() throws RemoteException.activation. 2000 Sun Microsystems. id.*. no distingue si es rmi normal o rmi activable.. All Rights Reserved. Cursos de Verano de Málaga . import java. * Un objeto se puede exportar de dos formas: a) heredando de Activatable b) llamando a exportObject(.).exportObject(this.rmi. . import java. public ActivatableImplementation(ActivationID id.. to construct the object.

ubicacionDeClass. * Son necesarios un CommandEnvironment junto con unas Properties para crear un descriptor de grupo de activación.. Capítulo 12: RMI.). donde los datosMarshalled suelen ser null.. . * Nótese como en ningún momento se hace un new del objeto que se pretende exportar.2005 -18- Ejemplo de activación * La clase CommandEnvironment permite cambiar las propiedades por defecto del sistema para un ActivationGroup concreto. * A continuación se crea el grupo con createGroup(.. * Es necesario registrar el descriptor para obtener un identificador de grupo de activación. * El descriptor se registra con una llamada de la forma: Activatable. * El descriptor de activación se crea con una llamada de la forma: new ActivationDesc (ClaseActivable.bind(..register(descriptor).Programación en Java.. lo que devuelve un objeto que habrá que registrar posteriormente de la manera tradicional. datosMarshalled).. Cursos de Verano de Málaga . con Naming.). sino que se le pueden dar datos por defecto mediante un objeto MarshalledObject.

Capítulo 13: Ejecución de programas no Java.exe a ejecutar.getRuntime(). JNI * Algunas veces es necesario hacer cosas muy dependientes de la máquina donde se va a ejecutar el programa Java. i*j). S * La comunicación con el fichero .exe pasan a ser su salida estándar y su entrada estándar. vaciar los bufferes cuando escribimos algo. JNI. scanf("%d %d". Se utiliza la clase Process. * La ejecución y comunicación con programas escritos en otro lenguaje es muy fácil. como C. &j).exec(). que admite como parámetro una cadena con el nombre del fichero . fflush(stdout). &i. j. que en el .h> void main() { int i. y el método estático Runtime. en C: #include <stdio.2005 -1- Capítulo 13: Ejecución de programas no Java. .Programación en Java.exe como en el programa Java. para asegurarnos de que el otro interlocutor lo recibe en ese mismo momento. R * Ej. } * No hay que olvidar tanto en el . printf("%d\n". Cursos de Verano de Málaga .exe es muy simple: en Java G creamos streams de entrada y de salida. * Dado que Java es independiente de la máquina hay que recurrir a otros lenguajes de programación.

"). JNI.io.println(lector. import java.2005 -2- Ejecución de programas no Java // Conexion."). } catch (IOException e) { System.out. System. DataInputStream lector.exe. Cursos de Verano de Málaga .println("34 56"). escritor = new PrintStream( new BufferedOutputStream( p.getRuntime(). System.flush().println("Imposible iniciar el ejecutable.exe. escritor.*. lector = new DataInputStream( new BufferedInputStream( p. .util. public class Conexion { public static void main(String[] args) { Process p.exit(1). escritor.println("Mando cosas al .exec("Mult.err.java import java.Programación en Java."). System.*.exe").getInputStream() ) ).out.readLine()). System. PrintStream escritor.out. try { p = Runtime.getOutputStream() ) ).println("Leo cosas del . } } } Capítulo 13: Ejecución de programas no Java.

class.2005 -3- JNI * JNI: Java Native Interface.Declarar las funciones C como native. * A los métodos escritos en C se les llama nativos.Generar un fichero de cabecera .displayHolaMundo().loadLibrary("nombre"). * Ej.Programación en Java. R . } public static void main(String[] args) { new HolaMundo(). JNI. Cursos de Verano de Málaga .dll en el caso de Windows) S * Desde el punto de vista de la clase Java. * JNI permite que una misma clase pueda tener unos métodos escritos en Java y otros métodos escritos en C.h asociado a la clase de Java. .loadLibrary("hello"). y no dotarlas de cuerpo. mediante la utilidad javah. sino en una librería dinámica (archivo . puesto que están compilados en código máquina y son nativos de un :p concreto.En la inicialización de la clase hay que cargar la librería que contendrá el cuerpo escrito en C (nombre. .: class HolaMundo { public native void displayHolaMundo(). sólo hay que hacer tres cosas: G . static { System.dll) de la forma: System. * El código de los métodos nativos no se coloca en el . } } Capítulo 13: Ejecución de programas no Java.

JNI. es necesario “decorar” el nombre de la función.C quedaría: #include "HelloWorld.h> JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env. Aunque hay ciertos criterios bien definidos para hacer esta decoración. Además se permite sobrecarga de funciones nativas.Programación en Java. Esto es así porque diferentes clases de Java pueden tener funciones nativas con el mismo nombre. * El programa . Capítulo 13: Ejecución de programas no Java. jobject obj) { printf("Hello world!\n"). el fichero cabecera que genera javah ya posee la declaración completa.h" #include <stdio. return.C generado por javah. que debe ser incluido en el fichero C que implementa la función nativa. } * La cabecera de la función ha sido copiada tal cual del fichero .h en lenguaje C.2005 -4- JNI * La utilidad javah genera un fichero de cabecera . . * La función nativa en el programa en C no tiene exactamente el mismo nombre con el que se ha declarado en Java. Cursos de Verano de Málaga . * Por tanto.

y al fichero jni_md. S * Algunas versiones del JDK 1.h ubicado en C:\jdk1. * Una libería . Suele ser necesario cambiar este punto de entrada a una función cualquiera inventada a tal efecto.2\include. JNI. y de cuerpo vacío.2005 -5- Compilación del programa C * El programa C debe dar lugar a una librería dinámica (.) JNI_OnLoad(.2\include\win32.Programación en Java.... y nunca a un programa . * El fichero .dll).dll generado ha de tener el mismo nombre que se usó en System.) JNI_CreateJavaVM(.) JNI_OnUnload(..h.dll suele tener un punto de entrada (LibMain()) con varios parámetros. Capítulo 13: Ejecución de programas no Java.2 pueden dar problemas debido a la definición de la macro JNIEXPORT. Cursos de Verano de Málaga ....exe.h que está en C:\jdk1. .) dentro de la cabecera jni.loadLibrary(.... * La cabecera incluye el fichero jni..) JNI_GetCreatedJavaVMs(..). En tales G circunstancias basta con eliminar dicha palabra en la declaración de las funciones: R JNI_GetDefaultJavaVMInitArgs(.

h: Tipo en Java boolean byte char short int long float double void Tipo en C jboolean jbyte jchar jshort jint jlong jfloat jdouble void 8 16 (sin signo) 16 32 64 32 64 -Tamaño en bits 8 (sin signo) * Los objetos de Java se pasan por referencia a los métodos nativos. y todos heredan de jobject. . Cursos de Verano de Málaga .Programación en Java.2005 -6- Paso de parámetros * Los tipos primitivos de Java son directamente accesibles desde C a través de los tipos predefinidos en jni. Además: Capítulo 13: Ejecución de programas no Java. JNI.

. jobject obj. Cursos de Verano de Málaga . jobject obj que se pasan de forma automática a toda función nativa: .ReleaseStringChars libera el puntero anterior. 0). desde dentro de una función nativa. .env es un puntero que nos permite acceder al entorno Java (environment).GetStringChars retorna un puntero a un array de Unicodes.) libera dicho array. * La siguiente función ilustra como hacer uso de un jstring : JNIEXPORT jstring JNICALL Java_Prompt_getLine(JNIEnv *env. .2005 -7- jstring * El tipo de C jstring se usa para acceder a parámetros Java de tipo String .. printf("%s". (*env)->ReleaseStringUTFChars(env. S G R Capítulo 13: Ejecución de programas no Java. . .GetStringUTFChars(..NewString construye un String Java a partir de Unicodes. } * Algunas funciones para manejar jstring son: . * El tipo jstring no es como el array de char de C. str).GetStringLength da la longitud de un array de Unicodes.obj es el objeto Java que recibe el mensaje nativo. . const char *str = (*env)->GetStringUTFChars(env. JNI. prompt. .) crea un array de chars en ASCII.ReleaseStringUTFChars(.Programación en Java. * El fichero jni... .GetStringUTFLength da la longitud de un array de ASCII. puesto que un jstring trabaja con Unicode y no con ASCII puro. jstring prompt) { char buf[128]. prompt... str). .h define muchas funciones que son accedidas a través de los parámetros JNIEnv *env.

arr.). jsize len = (*env)->GetArrayLength(env.Get<tipo>ArrayElements(. i++) { sum += body[i]..). static { System.out. JNI.Get<tipo>ArrayRegion(. ..println("sum = " + p. arr. 0). i++) arr[i] = i.. NIEXPORT jint JNICALL Java_IntArray_sumArray(JNIEnv *env. . jint *body = (*env)->GetIntArrayElements(env..). body. for (int i = 0.. i < 10.) permite obtener sólo un trozo del array. ..2005 -8- Arrays nativos * El tipo de C j<tipo>Array permite acceder a los arrays previa conversión. } public static void main(String args[]) { IntArray p = new IntArray(). int arr[] = new int [10]. .. Cursos de Verano de Málaga . 0). System.GetArrayLength(. } } Capítulo 13: Ejecución de programas no Java. arr). i<len.loadLibrary("MyImpOfIntArray")..Release<tipo>ArrayElements(. * El programa Java sería tan sencillo como: class IntArray { private native int sumArray(int arr[]).sumArray(arr)). for (i=0. jobject obj. jintArray arr) { int i. al igual que sucede con jstring. en lugar del array entero.Programación en Java. Se suele emplear cuando el array es muy grande y consume mucho espacio. } * Las funciones que se usan son: . sum = 0. } (*env)->ReleaseIntArrayElements(env. return sum.

.A partir del jfieldID se accede al campo que sea para leerlo con GetStatic<tipo>Field o Get<tipo>Field. Ello se consigue a través de la función GetObjectClass(env. Para escribirlo se usa SetStatic<tipo>Field o Set<tipo>Field. . Cursos de Verano de Málaga .Se obtiene un identificador del campo al que se quiere acceder (tipo jfieldID). Capítulo 13: Ejecución de programas no Java.2005 -9- Acceso al objeto principal. b) dos cadenas de caracteres que contienen el nombre del campo y su tipo “decorado” respectivamente.Programación en Java. Campos * Desde una función nativa es posible acceder a los campos miembro y de clase del objeto this que recibe el mensaje. en formato jclass. Estas funciones toman como parámetro (además de env): a) La clase del objeto principal. S G R 2. Consultar las opciones en la ayuda de javap. JNI. * El acceso a un campo tal se produce en dos fases: 1. Según sea estático o no. mediante GetStaticFieldID o GetFieldID. se pasará como parámetro un jclass o un jobject.. * El tipo “decorado” de cada campo se conoce gracias a la utilidad desensambladora javap con las opciones -s -p. Esto devuelve una lista con todos los elementos de la clase junto con su tipo “decorado” en un comentario adjunto. obj).

jfieldID fid.s + "\""). cls. fid. cls. } jstr = (*env)->GetObjectField(env.si = %d\n".s = "abc".2005 -10- Acceso al objeto principal. 200).println(" c. fid). jstr). static { System. c.s = \"%s\"\n". fid). . } private native void accessFields().println("In Java:").Programación en Java. Campos class FieldAccess { static int si.out. str). "I").h> #include "FieldAccess. obj). printf("In C:\n").si). printf(" c. si).accessFields().println(" FieldAccess.out. obj. System. c. 0). "123").si = " + FieldAccess. "Ljava/lang/String. FieldAccess. public static void main(String args[]) { FieldAccess c = new FieldAccess(). fid = (*env)->GetStaticFieldID(env. if (fid == 0) { return. printf(" FieldAccess. jstr = (*env)->NewStringUTF(env. if (fid == 0) { return.loadLibrary("MyImpOfFieldAccess"). str). (*env)->SetObjectField(env. const char *str."). jstr. System.h" JNIEXPORT void JNICALL Java_FieldAccess_accessFields(JNIEnv *env. obj.si = 100. "si". String s. jobject obj) { jclass cls = (*env)->GetObjectClass(env. } void alfa(){} /* Punto de entrada a la dll */ Capítulo 13: Ejecución de programas no Java. Cursos de Verano de Málaga . System. } } #include <stdio. JNI. fid = (*env)->GetFieldID(env. jint si. jstr. fid. (*env)->SetStaticIntField(env. (*env)->ReleaseStringUTFChars(env. jstring jstr. } si = (*env)->GetStaticIntField(env. cls.out. "s". str = (*env)->GetStringUTFChars(env. cls.s = \"" + c.

Programación en Java. Métodos * Desde una función nativa también es posible invocar métodos de un objeto.out. que aceptan un número variable de argumentos (en función de los definidos en la clase Java). } public static void main(String args[]) { Callbacks c = new Callbacks(). System. vuelta de Java\n". nivel = " + depth + ". vuelta de C"). "callback". entrando en Java\n". ya sea estático o no: . static { System. límite alcanzado"). } void alfa(){} Capítulo 13: Ejecución de programas no Java. Cursos de Verano de Málaga . obj). depth). (*env)->CallVoidMethod(env. depth). mid.println("En Java. JNI. } printf("En C.println("En Java. class Callbacks { private native void nativeMethod(int depth). entrando en C"). } } S * Hay otros métodos de invocar funciones. } private void callback(int depth) { if (depth < 5) { System. .out.nativeMethod(0). jint depth) { jclass cls = (*env)->GetObjectClass(env.h> #include "Callbacks. nivel = %d.Los identificadores de los métodos se toman con GetMethodID o GetStaticMethodID.println("En Java.h" JNIEXPORT void JNICALL Java_Callbacks_nativeMethod(JNIEnv *env. nivel = %d.Los métodos se invocan con Call<tipo>Method o CallStatic<tipo>Method. cls.loadLibrary("MyImpOfCallbacks").2005 -11- Acceso al objeto principal. return. jmethodID mid = (*env)->GetMethodID(env. } else System. . c.out. obj. jobject obj. nativeMethod(depth + 1). if (mid == 0) { return. nivel = " + depth + ". printf("En C. "(I)V"). depth). nivel = " + depth + ". Ambos devuelven un jmethodID. G R #include <stdio.

Programación en Java.2005 -12- Manejo de excepciones * Una función nativa puede detectar si se ha producido una excepción al llamar a una función Java pura con: jthrowable exc = (*env)->ExceptionOccurred(env). Cursos de Verano de Málaga . if (exc) {/*Excepción producida*/} * La función nativa puede elevar excepciones con: newExcCls = (*env)->FindClass(env. JNI. "thrown from C code"). . newExcCls. Capítulo 13: Ejecución de programas no Java. if (newExcCls == 0) { /* No se ha podido encontrar la clase */ return. * La función nativa también puede corregir una excepción elevada con: (*env)->ExceptionClear(env). } (*env)->ThrowNew(env. "java/lang/IllegalArgumentException").

jar. que es una clase que almacena información relativa a un idioma hablado en un determinado país. Capítulo 14: Internacionalización. S G a un conjunto de recursos * La clase Locale hace referencia de un idioma concreto: ResourceBundle. * El proceso se basa en los llamados Locale. * Las clases destinadas a la internacionalización se hallan en el archivo i18n.Programación en Java. * A continuación se muestra el contenido de los recursos i18n para los distintos idiomas admitidos. los mensajes se recogen mediante getString(.. . Cursos de Verano de Málaga ..). R * El siguiente ejemplo ilustra cómo se utiliza un objeto Locale para acceder a un ResourceBundle. El nombre de este archivo se deriva de que la palabra internacionalización posee 18 letras entre la i inicial y la n final.2005 -1- Capítulo 14: Internacionalización * Java dispone de mecanismos que facilitan la migración de programas escritos en un idioma a otro diferente. A continuación.

despedida = Goodbye. . currentLocale = new Locale(language.properties: bienvenida = Buenos días. pregunta = How are you? Fichero MessagesBundle_es_ES.properties: bienvenida = Hallo.getString("bienvenida")). Inc. country = new String("ES").println(messages. Cursos de Verano de Málaga . pregunta = ¿Cómo está? Capítulo 14: Internacionalización. String country.2005 -2- I18n: Ejemplo básico // Copyright (c) 1995-1998 Sun Microsystems. System. } else { language = new String(args[0]).out. Import java. messages = ResourceBundle.currentLocale).length != 2) { language = new String("es").Programación en Java. System. } Locale currentLocale.*. if (args.out.util.getBundle("MessagesBundle". country). All Rights Reserved.properties: bienvenida = Hello. System. ResourceBundle messages. pregunta = Wie geht's? Fichero MessagesBundle_en_US.getString("pregunta")). despedida = Tschüß.println(messages. country = new String(args[1]). } } Fichero MessagesBundle_de_DE.getString("despedida")).out. despedida = Adiós. public class I18NSample { static public void main(String[] args) { String language.println(messages.

Programación en Java. Capítulo 14: Internacionalización. fechas y valores monetarios. Cursos de Verano de Málaga .2005 -3- Aspectos a internacionalizar * Muchos son los aspectos a considerar cuando se cambia de idioma un programa: T Mensajes T Etiquetas sobre componentes GUI T Ayuda en línea T Sonidos T Colores T Gráficos T Iconos T Fechas T Horas T Números T Valores monetarios T Medidas T Números de teléfono T Títulos honoríficos y personales T Direcciones de correo postal T Distribución de páginas S G R * Trabajaremos con mensajes que intercalan datos. .

. * Para solucionar este problema se hace uso de la clase MessageFormat. en inglés la hora iría antes que la fecha. almacenados en un array de Object. Cursos de Verano de Málaga .Por último. que permite expresar en un fichero de recursos una expresión completa: .Luego se le aplica un patrón que se encuentra en el ResourceBundle correspondiente. además de otra información de formato. p. .Un objeto de tipo MessageFormat se asocia con un Locale.ej.Programación en Java. éste mensaje se formatea con los parámetros que se quiera. * Los patrones posibles pueden consultarse en la ayuda de MessageFormat: se colocan entre llaves y llevan el número del parámetro del que toman los datos. se detectaron 7 naves sobre el planeta Marte” * En otros idiomas. los datos pueden ir intercalados de otra forma. . Capítulo 14: Internacionalización.2005 -4- Texto y datos intercalados * A menudo es necesario intercalar datos entre el texto: “El 13 de abril de 1998 a las 1:15.

System. MessageFormat formatter = new MessageFormat("").out.out.format(messageArguments).getString("planet"). "US")). Cursos de Verano de Málaga . . formatter.out.out.util.println(output). System. ResourceBundle messages = ResourceBundle.integer} spaceships on the planet {0}.date. import java.setLocale(currentLocale).date.currentLocale). "ES")).time. displayMessage(new Locale("en". String output = formatter.properties: template = At {2.Programación en Java.long}. new Date() }.*. formatter. } } S G R Fichero MessageBundle_en_US. } static public void main(String[] args) { displayMessage(new Locale("es".println("currentLocale = " + currentLocale. public class MessageFormatDemo { static void displayMessage(Locale currentLocale) { System. new Integer(7).text.toString()).integer} naves sobre el planeta {0}.*.time. System.println(). se detectaron \ {1.applyPattern(messages.number.long} a las {2.short}.properties: template = El {2. planet = Marte Capítulo 14: Internacionalización.println(). planet = Mars Fichero MessageBundle_es_ES.2005 -5- Ejemplo con MessageFormat import java.number. we detected \ {1.getString("template")). Object[] messageArguments = { messages.getBundle("MessageBundle".short} on {2.

FULL Capítulo 14: Internacionalización.out.length..DateFormat. Cursos de Verano de Málaga . for (int i = 0. .getAvailableLocales().Se crea un objeto de tipo DateFormat mediante un getDateInstance(..DateFormat.2005 -6- Formato de fechas y horas * A estos efectos. .toString()).MEDIUM . * Los estilos de fechas que se pueden sacar son: .DateFormat. i<l.DateFormat. Probar los disponibles con el programa: import java...LONG . } } } * Se realiza mediante un proceso en dos fases: . i++){ System. el sistema dispone de forma predeterminada de algunos Locale.println(l[i]. .DateFormat.) toma como parámetros el estilo de fecha que se quiere sacar y el Locale correspondiente.Programación en Java.SHORT .getDateInstance(.*.).Se indica la fecha a convertir.util.DEFAULT . public class DameLocales { public static void main(String[] args){ Locale[] l = Locale.

for (int k = 0.text.getDateInstance( DateFormat. DateFormat. styles[k]. } } Capítulo 14: Internacionalización. Ejemplo import java.2005 -7- Fechas y horas. static DateFormat formatter. static public void showDateStyles(Locale currentLocale) { global(currentLocale)."ES").println().format(today).println(result).length. showTimeStyles(new Locale("es"."DE").Programación en Java.length. i++) displayDate(locales[i])."US") }.SHORT. new Locale("en". currentLocale).out. for (int k = 0.println(result).out. static public void global(Locale currentLocale){ System.FULL }.println(result). k < styles.length.toString()). import java. DateFormat dateFormatter. } static public void displayDate(Locale currentLocale) { Date today. DateFormat. currentLocale).DEFAULT. currentLocale)."FR")).util. System.println().println(dateOut + " " + currentLocale. System."FR"). static String result. String dateOut. dateFormatter = DateFormat.format(today)."ES")).getDateInstance(styles[k]. for (int k = 0. } } static public void main(String[] args) { Locale[] locales = { new Locale("fr". k++) { formatter = DateFormat. DateFormat. static int[] styles = { DateFormat.format(today)."ES"))."DE")). new Locale("es"."ES")). k < styles.format(today). result = formatter.getDateTimeInstance( styles[k]. showBothStyles(new Locale("en". dateOut = dateFormatter. today = new Date().LONG. .out. result = formatter.getTimeInstance(styles[k].println("Locale: " + currentLocale. new Locale("de".*."US")). k++) { formatter = DateFormat.toString()). showTimeStyles(new Locale("de". showDateStyles(new Locale("es". DateFormat.out. currentLocale). System. showBothStyles(new Locale("es". result = formatter. Cursos de Verano de Málaga . i < locales.out.*. k < styles.MEDIUM. System.out. } } System.length.out. System. for (int i = 0. } S G R static public void showTimeStyles(Locale currentLocale) { global(currentLocale). } public class DateFormatDemo { static Date today=new Date(). k++) { formatter = DateFormat.DEFAULT. showDateStyles(new Locale("fr". } static public void showBothStyles(Locale currentLocale) { global(currentLocale).

* Los símbolos que se pueden utilizar son: Symbol G y M d h H m s S E D F w W a k K z ' ' Meaning era designator year month in year day in month hour in am/pm (1-12) hour in day (0-23) minute in hour second in minute millisecond day in week day in year day of week in month week in year week in month am/pm marker hour in day (1-24) hour in am/pm (0-11) time zone escape for text single quote Presentation Text Number Text & Number Number Number Number Number Number Number Text Number Number Number Number Text Number Number Text Delimiter Literal AD 1996 Example July & 07 10 12 0 30 55 978 Tuesday 189 2 (2nd Wed in July) 27 2 PM 24 0 Pacific Standard Time (none) ' Capítulo 14: Internacionalización.Programación en Java. . Cursos de Verano de Málaga .2005 -8- Patrones para fechas y horas * Es posible utilizar SimpleDateFormat (que hereda de DateFormat) para utilizar nuestro propio formato de fecha.

println("Result: " + result). today = new Date().2005 -9- Ejemplo de formato * El siguiente trozo de programa: Date today. String result.out. de días. result = formatter. podría emitir por pantalla: Locale: fr_FR Result: ven 10 avr 98 Locale: de_DE Result: Fr 10 Apr 98 Locale: en_US Result: Thu 9 Apr 98 S G R * La clase DateFormatSymbol permite realizar modificaciones sobre los símbolos utilizados a la hora de visualizar nombres de meses.format(today). System.out. System. formatter = new SimpleDateFormat("EEE d MMM yy". etc. Capítulo 14: Internacionalización. currentLocale). SimpleDateFormat formatter. .println("Locale: " + currentLocale.toString()).Programación en Java. Cursos de Verano de Málaga .

toString()).format(quantity). currencyOut = currencyFormatter. new Locale("de". displayNumber(locales[i]).*. i++) { System. . new Locale("es". amountOut = numberFormatter. i < locales.out.out.println(currencyOut + " " + currentLocale.getCurrencyInstance(currentLocale). NumberFormat percentFormatter. String quantityOut.getPercentInstance(currentLocale).21). } static public void displayCurrency(Locale currentLocale) { Double currency = new Double(9876543. }}} Capítulo 14: Internacionalización.Programación en Java. Double amount = new Double(345987. “EURO”) }."US"). new Locale("en". System. public class NumberFormatDemo { static public void displayNumber(Locale currentLocale) { Integer quantity = new Integer(123456).75). import java. percentFormatter = NumberFormat. } static public void displayPercent(Locale currentLocale) { Double percent = new Double(0. Cursos de Verano de Málaga . displayCurrency(locales[i]).toString())."DE").out. System. System.toString()).length. } static public void main(String[] args) { Locale[] locales = {new Locale("fr". String currencyOut. String amountOut. new Locale("es". Básicamente se pueden gestionar: Números. NumberFormat currencyFormatter. numberFormatter = NumberFormat. quantityOut = numberFormatter.text.*. NumberFormat numberFormatter.println(percentOut + " " + currentLocale. System. for (int i = 0.toString()).format(percent). String percentOut. Valores monetarios y Porcentajes.getNumberInstance(currentLocale).out.println(amountOut + " " + currentLocale. import java.util."ES"). displayPercent(locales[i]).246).out."FR").format(amount). currencyFormatter = NumberFormat.println(quantityOut + " " + currentLocale.format(currency). percentOut = percentFormatter.2005 -10- Formato de números * Los números se gestionan de forma parecida a las fechas.println()."ES".

format(value). % ? $ un dígito un dígito. . o cero si no existe Lugar para el separador decimal lugar para el separador de grupo separa la mantisa y el exponente en el formato exponencial separa formatos Description S G R prefijo negativo por defecto multiplica por 100 y visualiza un porcentaje Multiplica por 1000 y visualiza como “por milla” signo monetario se reemplaza por el símbolo monetario. si aparece en un patrón se utilizará el separador decimal monetario en lugar del separador se puede usar cualquier carácter como prefijo o sufijo se emplea para entrecomillar caracteres especiales en un prefijo o sufijo X ' Capítulo 14: Internacionalización. si aparece duplicado se reemplaza por el símbolo monetario internacional.Programación en Java.toString()). System.2005 -11- Patrones para números * También es posible utilizar patrones con los números.applyPattern(pattern).println(pattern + " " + output + " " + loc.: NumberFormat nf = NumberFormat. * Los símbolos que se pueden usar en los patrones son: Symbol 0 # . E . DecimalFormat df = (DecimalFormat)nf. . Ej.getNumberInstance(loc). String output = df.out. df. Cursos de Verano de Málaga .

i < words.length.length. Collator en_USCollator = Collator..2005 -12- Ordenación * La mayoría de idiomas existente. i++) { for (int j = i + 1.compare(words[i].). * En estos idiomas. words[i] = words[j]. He aquí un ejemplo: public static void sortStrings(Collator collator."US")). Cursos de Verano de Málaga . es necesario suministrar una serie de reglas para que esas letras de más sean consideradas a la hora de realizar ordenaciones alfabéticas. for (int i = 0. Capítulo 14: Internacionalización. posee un conjunto de caracteres que extiende de alguna manera el del idioma inglés. ."FR")). j < words. String[] words) { String tmp. words[j] = tmp. } } } } que puede ser llamado con los Collator: Collator fr_FRCollator = Collator.Programación en Java. que integra la capacidad de ordenar texto mediante Compare(. words[j]) > 0) { tmp = words[i]. * Para ello se emplea la clase Collator..getInstance(new Locale("fr". j++) { if (collator.getInstance(new Locale("en".

E < f.Y < z. import java. printStrings(words).U < v.X " + "< y.E < f. } catch (ParseException pe) { System.O < p. words[j] = tmp. try { RuleBasedCollator enCollator = new RuleBasedCollator(englishRules).I < j. i < words. words[j] ) > 0){ // Swap words[i] and words[j] tmp = words[i].println(words[i]).V < w.Q < r.S < t.G < h.M < n.out.W < x. cH.V < w. printStrings(words). sortStrings(spCollator.C " + "< ch.compare(words[i].H < i.Z").R " + "< s. String smallnTilde = new String("\u00F1").F " + "< g.Q < r.R " + "< s. i < words.G < h. words[i] = words[j].A < b.K < l. "curioso".C < d.W < x.D < e. RuleBasedCollator spCollator = new RuleBasedCollator(traditionalSpanishRules).H < i. } } } } public static void printStrings(String [] words) { for (int i = 0.println("Parse exception for rules").Y < z.L " + "< ll. } } static public void main(String[] args) { String englishRules = ("< a. String traditionalSpanishRules = ("< a. Ll. import java." + capitalNTilde + " " + "< o.A < b. S G R String [] words = { "luz". i++) { for (int j = i + 1. . CH " + "< d.P < q.length.F " + "< g.Z"). System.D < e.I < j.L " + "< m. Cursos de Verano de Málaga .B < c.J < k. for (int i = 0.out.println().*.2005 -13- Reglas de ordenación * A través de la clase RuleBasedCollator. String[] words) { String tmp.Programación en Java.*. j < words.length. "chalina" }.length. sortStrings(enCollator. Ch.K < l. lL.util.U < v. j++) { // Compare elements of the words array if( collator.T < u. i++) { System. "llama".M < n.P < q.S < t. LL " + "< m.X " + "< y.T < u.N < o. words).N " + "< " + smallnTilde + ".out.B < c.text. words).O < p.J < k. } } } Capítulo 14: Internacionalización. public class RulesDemo { public static void sortStrings(Collator collator. es posible crear nuestras propias reglas de ordenación. String capitalNTilde = new String("\u00D1").