Total Java

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 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. 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 .DD. El servidor La comunicación RMI. Servidor Servlets HTML y formularios Ciclo de vida de un servlet Clases para servlets Ejemplo de servlet Capítulo 12: RMI RMI. El servidor (cont.Creación de tablas en HTML Internet y BB.DD. Campos Acceso al objeto principal. JNI Ejecución de programas no Java JNI. Compilación del programa C Paso de parámetros jstring Arrays nativos Acceso al objeto principal. El applet Internet y BB.) RMI. 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.

Depuración Manipulación del cuerpo Ejemplo de bucle Ámbito de objetos Etiquetas anidadas Bases de datos Etiquetas Java Descriptor de etiquetas . 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.Primer ejemplo Expresiones JSP Scriptlets Scriptlets y condiciones Declaraciones Directiva page.

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

2005 -2- Características generales * Originalmente. 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.Programación en Java. .Ejecutores JIT (Just In Time).Compiladores que generan código nativo (código máquina) en lugar de pseudocódigo. y controla más condiciones de error que otros lenguajes. * ¿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. * Java es seguro. * Para evitar aproximaciones: la lentitud hay dos . Éstos. Java era muy lento. . Impide accesos indebidos. Capítulo 0: Introducción. pero actualmente emplea optimizaciones que sólo lo hacen 2 veces más lento que C++. a medida que van traduciendo el pseudocódigo a código máquina y lo van ejecutando. como C++. Con esto se pierde portabilidad. ya que es pseudointerpretado. dejan el código máquina traducido en un buffer para no tener que volver a traducirlo. Cursos de Verano de Málaga .

0. tanto si la máquina es multiprocesador como si no. Actualmente hay varias versiones fundamentales del JDK (Java Development Kit) que son: 1. * Por desgracia.3. R . * Java es un lenguaje multitarea. * Java permite trabajar con Bases de Datos vía JDBC (Java DataBase Connectivity). 1.1 (las más antiguas). Capítulo 0: Introducción. 1. Cursos de Verano de Málaga . 1. S * En Java no es tan importante el lenguaje como G las librerías que ya incorpora. 1.5 (JDK 5). Java evoluciona a un ritmo vertiginoso.4 (conocidas como JDK 2) y 1.2005 -3- Características generales * Java permite tener las distintas partes que componen un programa distribuídas por la red.Programación en Java.2. * 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.

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

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

@deprecated Los métodos marcados con deprecated hacen que el compilador emita una advertencia (warning) si se utilizan. 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. Cursos de Verano de Málaga . * Para ello se utiliza un comentario que empieza por /** y acaba con */ * Estos comentarios deben colocarse siempre justo antes de una clase. y la coloca en un fichero HTML. * Existe una herramienta llamada javadoc que extrae documentación automáticamente de nuestros programas. y pueden ser: Para todos (el único admitido por los campos): @see NombreDeClase Permite referenciar a la documentación de otras clases. Capítulo 0: Introducción.2005 -6- Comentarios * En Java los comentarios son como en C. . un campo o un método.

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

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

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

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

Capítulo 1: Conceptos O. . de Java.Programación en Java. métodos y variables métodos y variables clases. Cursos de Verano de Málaga . interfaces. interfaces.O. Modificador Se aplica a Ella Package Hijas Otras misma clases public clases.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.0 de Java. 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.

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

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

que además de frío puede dar calefacción. No se puede hacer al revés (control de bomba de calor y sólo sistema de aire acondicionado). Hay veces en las que interesa que la interfaz de la clase hija sea más rica que la del padre.Programación en Java. Es lo que se llama sustitución pura. .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. Ej. No se cambia el panel de control. ya que ambos tienen la misma interfaz. Sea el panel de control del aire acondicionado. Aunque el nuevo objeto (la bomba de calor) tiene una interfaz más completa. Se nos rompe el sistema de aire acondicionado.: Sea un sistema de aire acondicionado. Capítulo 1: Conceptos O. El panel de control controla al sistema. un manejador a objetos padre. también puede apuntar a objetos hijos. Cursos de Verano de Málaga .O. Se sustituye por una bomba de calor. nuestro manejador no nos permite la comunicación. De esta forma. quiere decir que un manejador puede apuntar tanto a objetos de la clase padre como a los de la clase hija. de Java. pero (debido a su definición) sólo podrá dirigir los mensajes que el padre tiene definidos.

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

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

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

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

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

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

2005 -15- Multitarea p Java emplea el concepto de multithreading. R p Las tareas deben implementar la interfaz Runnable. p Si la máquina posee varios procesadores.Programación en Java. p Java permite la creación de tareas o subprogramas de ejecución independiente. había que recurrir a las interrupciones. Esto hace que el código sea muy dependiente de la máquina. p En lenguajes anteriores. S G p Cualquier programa puede dividirse en las tareas que se quieran. Capítulo 1: Conceptos O.O. . Es lo que se llaman threads. 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. para simular que se hacen varias cosas a la vez. de Java. Cursos de Verano de Málaga .

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

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

sino en la facilidad de programar. como en cualquier otro lenguaje.O. y en que produce programas mucho más robustos.No es necesario recoger la memoria con dispose o free.2005 -18- Java y aplicaciones standalone p Puede emplearse el lenguaje Java para hacer aplicaciones completas. de Java. .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. .Se hacen chequeos de límites de arrays. Cursos de Verano de Málaga . estas restricciones no existen en las aplicaciones independientes o standalone.Se hacen potentes chequeos de tipos. sino que el propio sistema se encarga de ello a través del recolector de basura.Programación en Java. en el sentido de que: . . Capítulo 1: Conceptos O. .

sólo estamos declarando el manejador. Todos los objetos se crean R siempre con new. S G * Los manejadores sólo tienen sentido cuando se conectan a un objeto de verdad. . y nunca directamente.Programación en Java. si se hace: String s. P.2005 -1- Capítulo 2 Objetos en Java p En Java los objetos se gestionan a través de manejadores.ej. String s. pero no ningún objeto de tipo String. s = new String("abcd"). y se conectan a los manejadores mediante el símbolo de asignación =. Capítulo 2: Objetos en Java.. * 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. Cursos de Verano de Málaga .

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

0d 0 0 0 * El tamaño es siempre el mismo independientemente de la máquina. int i = 16.0f R 0. // I es un manejador. .2005 -3- Tipos básicos o primitivos p Hay una excepción a la regla «Todo son objetos en Java». // i es un tipo primitivo. 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. Capítulo 2: Objetos en Java. * Para poder trabajar con los tipos primitivos como si fueran clases. Cursos de Verano de Málaga .En un tipo primitivo el tipo y el objeto son la misma cosa.Programación en Java. cada tipo primitivo tiene una clase asociada llamada wrapper. Integer I = new Integer(16). aunque siempre a través de manejadores. La excepción la suponen los tipos primitivos. que puede almacenar el mismo tipo de información.

Por tanto cuidado con el operador ==. ya que se le puede pasar directamente un valor primitivo. . Capítulo 2: Objetos en Java. las sentencias: int x. x = i. producirían un error en ejecución ya que los tipos primitivos no pueden albergar el valor null.5 permite el autoboxing o autoconversión. las siguientes sentencias son válidas a partir de JDK 1.5: Integer i = 7. int x = new Integer(8). Cursos de Verano de Málaga . Así.Programación en Java. Integer i = null. * La autoconversión es realizada por el compilador por lo que internamente un tipo primitivo sigue siendo diferente de su tipo wrapper. * Sin embargo. * La autoconversión es especialmente útil cuando una función espera un tipo wrapper. * El JDK 1.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.

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

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

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

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

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

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

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

Cursos de Verano de Málaga .list(System.util. * El signo + indica concatenación cuando se utiliza con cadenas de caracteres.println(new Date()).println( "Total de memoria = " + rt. } } * 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.freeMemory()).out. Capítulo 2: Objetos en Java. * Date es un objeto que se crea con el único objetivo de pasárselo como parámetro a System.java import java.getProperties().getRuntime(). p.*.Programación en Java. System.totalMemory() + "Memoria libre = " + rt.println("---Uso de memoria:").2005 -12- El primer programa // Propiedades. * La clase que se desea ejecutar debe tener una función miembro estática llamada main() que recibe como argumento un array de String. 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). public class Propiedades { public static void main(String[] args) } System.println. Properties p = System.out).out. que serán los parámetros que se le pasen desde la línea de comandos.out. Runtime rt = Runtime.

<< >> >>> > < >= <= == != 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++. En estos casos. lo que se hacen son copias de los datos concretos. * No ocurre lo mismo cuando se trabaja con manejadores de objetos. lo que ocurre es que el manejador lvalor referencia al mismo objeto que el manejador r-valor. dado que no intervienen manejadores. .++ -* / % + .Programación en Java. 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 + . Cursos de Verano de Málaga . Capítulo 2: Objetos en Java.

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

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

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

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

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

de flujo * El bucle for tiene dos formatos. sentencias de paso. Cursos de Verano de Málaga . } 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. } Capítulo 2: Objetos en Java. y otro para recorrer arrays y colecciones (que se verán más adelante). uno equivalente al del lenguaje C.2005 -19- Sentencias de ctrl. for (int i : a) resultado += i. while(expresión boolean) { sentencia. * for( sentencias de inicio. return resultado. expresión boolean. . sentencias de paso) sentencia equivale a: sentencias de inicio.Programación en Java.

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

El único problema es que desde el manejador no se tiene acceso a las extensiones del objeto apuntado. Si no lo es se genera la excepción ClassCastException.Programación en Java. Cursos de Verano de Málaga .2005 -24- Downcasting * Hacer upcasting es una operación segura. * Por downcasting se entiende especificar que un manejador de una clase padre está apuntando a un objeto de una clase hija. 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. . 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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.draw(this). for (Figura f: figuras) { f. h). Capítulo 5. entonces el usar <? extends T> aumentará la flexibilidad. 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).. public void dibujaTodo(List<? extends Figura> figuras) { historial. * La expresión ? super T quiere decir «algo desconocido que es supertipo de T». // ¡Bien! * Usualmente. Hundir<? super T> hnd){.Programación en Java. Si la API sólo usa T para retornar cosas.addLast(figuras). si los métodos de una API muy general sólo usan el tipo formal en los argumentos. la clase Comparable o el método equals). Collection<String> cs. el usar <? super T> será beneficioso (ej. Ej.: static List<List<? extends Figura>> historial = new ArrayList<List<? extends Figura>>(). String str = escribirTodo(cs.: public static <T> T escribirTodo( Collection<T> col.} Hundir<Object> h.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 .5: Clases genéricas .

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

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

la integridad de la máquina virtual de Java G nunca se pone en peligro. Capítulo 5. * Cuando se utiliza acotación múltiple. R la forma: T & T & . * El motivo de esto es que el compilador de Java implementa los genéricos mediante una conversión front-end denominada erasure.. & * 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 &.5: Clases genéricas .add(x). xs.. el tipo real que se utiliza en la erasure es el primero de la lista.iterator(). } al ejecutarlo se producirá un fallo. a pesar de las unchecked warnings.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>(). List xs = ys. S * En cualquier caso. Cursos de Verano de Málaga .Programación en Java. // unchecked warning return ys.next().

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

2.976e+24.688e+26.Programación en Java.9e+27. double gravedadEnSuperficie() { return G * masa / (radio * radio).37814e6).024e+26. // en kilogramos private final double radio. 2.1492e7). } } S G R Capítulo 5. NEPTUNO (1. this.radio = radio.303e+23. 7. MARTE (6.0268e7). * El siguiente ejemplo ilustra cómo es posible asignar información (masa y radio) a los enumerados: public enum Planeta { MERCURIO (3.67300E-11.5: Clases genéricas . 1. JÚPITER (1.4746e7).27e+22.869e+24.421e+23. SATURNO (5. 2. } double pesoEnSuperficie(double otraMasa) { return otraMasa * gravedadEnSuperficie(). double radio) { this.3972e6).2005 -13- Constructor de enumerados * La invocación Estación. // en metros Planeta(double masa.137e6). Cursos de Verano de Málaga .masa = masa. 6. TIERRA (5. } // Constante gravitacional universal (m 3 kg -1 s -2) public static final double G = 6. 3. 6.5559e7).0518e6). private final double masa. PLUTÓN (1.686e+25. URANO (8. 6. VENUS (4.4397e6).values() devuelve un array de objetos de tipo Estación.

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

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

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

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

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

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

. toda función puede lanzar RuntimeException. Cursos de Verano de Málaga .dispose(). //: LostMessage. try { lm. } public static void main(String[] args) throws Exception { LostMessage lm = new LostMessage().Programación en Java. * finally se ejecuta aunque la excepción no sea capturada. * 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. } } public class LostMessage { void f() throws VeryImportantException { throw new VeryImportantException(). } } class HoHumException extends Exception { public String toString() { return "A trivial exception". } } } S G R Capítulo 6: Tratamiento de excepciones. y sin necesidad de especificarlo.2005 -5- Detalles sobre excepciones * De forma implícita.f(). * Hay que tener cuidado con la pérdida de excepciones. } finally { lm. 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!". } void dispose() throws HoHumException { throw new HoHumException().java // Copyright (c) Bruce Eckel.

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

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

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

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

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

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

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

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

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

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

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

2005 -12- StreamTokenizer import java. System.*.out. Capítulo 7: E/S con Java.nextToken() != StreamTokenizer.out.out.out.ordinaryChar('-'). posee el valor de dicho número como double.Programación en Java. TT_EOF.println("Una palabra: " + s). st. .'). 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.sval: Si el token es una palabra.ttype). contiene a dicha palabra. break. * Es una alternativa para la lectura desde el teclado.TT_EOF) { String s.println("Un carácter: " + s). case StreamTokenizer.println( "st. // Already a String System. Indica el tipo del token actual: TT_EOL.*.ordinaryChar('. try { while(st. TT_WORD. * Posee los siguientes elementos: . } } } * 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.sval. o un carácter si no es ninguno de ellos.TT_WORD: s = st.util. break.nextToken(). Cursos de Verano de Málaga . default: // single character in ttype s = String.ttype) { case StreamTokenizer. st.TT_NUMBER: d = st. .nval: Si el token es un número.io.TT_EOL: System. Carga el siguiente token. System. break. import java.nextToken() unsuccessful"). . switch(st.println("Un número: " + d). case StreamTokenizer.in).nval.ttype. . double d.out.valueOf((char)st.println("Fin de linea"). } } } catch(IOException e) { System. TT_NUMBER.

1 ha sustituído casi todas las clases que hemos visto por otras nuevas más eficientes.2005 -13- E/S con Java 1.Programación en Java. Capítulo 7: E/S con Java. Cursos de Verano de Málaga . . * 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.

* Se puede convertir un OutputStream en un Writer mediante el estrato OutputStreamWriter. . Capítulo 7: E/S con Java.2005 -14- E/S con Java 1. 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.Programación en Java.1 Salida * Para la salida son: Raíz principal: Antes: OutputStream Descendientes directos: Antes: ByteArrayOutputStream Ahora: Ahora: Writer CharArrayWriter StringBufferOutputStream. Cursos de Verano de Málaga .

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

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

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

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

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

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

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

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

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

Cursos de Verano de Málaga .getInterfaces(). Class cy = c. // (*1*) } catch(InstantiationException e) {} catch(IllegalAccessException e) {} printInfo(o. } } Capítulo 8: Metaclases.java // Copyright (c) Bruce Eckel. for(int i = 0. i++) printInfo(faces[i]). Class[] faces = c. 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. Object o = null.forName("FancyToy").isInterface() + "]").getName() + " is interface? [" + cc. } catch(ClassNotFoundException e) {} printInfo(c).getSuperclass(). . try { // Requires default constructor: o = cy. Waterproof. i < faces.2005 -2- Ejemplo //: ToyTest. try { c = Class. } } public class ToyTest { public static void main(String[] args) { Class c = null.getClass()).length.Programación en Java.newInstance(). ShootsThings { FancyToy() { super(1).out. } static void printInfo(Class cc) { System.println( "Class name: " + cc.

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

y su descripción. su R tipo.html pasa los parámetros a través de la etiqueta <PARAM>.56> <param name=DOS value=100> Applets no soportados.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. por lo que si el parámetro es numérico habrá que transformarlo convenientemente. Sobre cada parámtero se devuelve su nombre.Programación en 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."> <param name=TRES value=102. el fichero . . * getParameter() recoge siempre una cadena. <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. * Los parámetros se recogen desde el applet a través de getParameter(). Cursos de Verano de Málaga .2005 -7- Paso de parámetros en un applet * Como hemos visto.

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

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

2005 -10- Ventanas * Más interesante. ya que no tienen las restricciones de los applets. * La librería AWT (Abstract Windows Toolkit) suministra todos los componentes necesarios para aplicaciones Windows. que los applets son las aplicaciones independientes. . si cabe. 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). a la que se van añadiendo los componentes que queremos que integren nuestra aplicación. Capítulo 11: Programación Windows con Java.Programación en Java.

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

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

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

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

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

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

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

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

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

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

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

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

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

20)).setText("Radio button 1"). add(t).CENTER. t. Checkbox cb1 = new Checkbox("one". CheckboxGroup g = new CheckboxGroup(). add(cb1). else return super. g.target == this) { System. add(cb3).equals(cb3)) t. } public boolean action (Event evt.show(). } } Capítulo 11: Programación Windows con Java. } public static void main(String[] args) { RadioButton1 f = new RadioButton1(). . 30). } public boolean handleEvent(Event e) { if (e.setEditable(false). false). Cursos de Verano de Málaga .equals(cb2)) t.setText("Radio button 2").awt. //: RadioButton1.target.println("Frame eliminado. f.id == Event. true). public RadioButton1() { setLayout(new FlowLayout( FlowLayout. f. System. g. else if(evt.handleEvent(e). 200). * 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. 20.*. public class RadioButton1 extends Frame { TextField t = new TextField("Radio button 2". else if(evt.equals(cb1)) t.target. g.exit(0).").out. return true. cb3 = new Checkbox("three". arg).java // Using radio buttons import java. Object arg) { if(evt.target. } return super.setSize(300.WINDOW_DESTROY && e. add(cb2).Programación en Java.setText("Radio button 3").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. cb2 = new Checkbox("two". false). * Antes de visualizar un CheckboxGroup debe haber uno y sólo un Checkbox activado.action(evt.

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* 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 línea comienza con <TR>.Empiezan por <TABLE> y acaban con </TABLE>. .Cada dato de cada columna comienza por <TD>. Capítulo 11: Programación Windows con Java.Cada cabecera de cada columna comienza por <TH>. . . Cursos de Verano de Málaga .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Programación en Java. * * 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.2005 -13- Política de seguridad * La política de seguridad se puede cambiar de varias maneras: .security. public synchronized void checkAccess(ThreadGroup g) {} // Loaded classes are allowed to access the system properties list. /** * Esta clase define una política de seguridad para aplicaciones * RMI cargadas desde un servidor.policy.Mediante la propiedad java. consultar la clase RMISecurityManager. public synchronized void checkAccess(Thread t) {} // Loaded classes are allowed to manipulate thread groups. . . public synchronized void checkPropertiesAccess() {} } * Para más información. int port) {} // Loaded classes are allowed to manipulate threads. . La relajación suministrada por * esta clase es la mínima necesaria para que todo funcione. Cursos de Verano de Málaga .Creando un nuevo SecurityManager // Copyright MageLang Institute. Capítulo 12: RMI.policy.Mediante el fichero java. public synchronized void checkCreateClassLoader() {} // Connections to other machines are allowed public synchronized void checkConnect(String host.

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

hay que ejecutar en background el dispensador de activaciones R rmid (RMI daemon). . > Datos de inicialización en formato plano (marshalled). . rmiregistry debe estar activado también.El activador busca el descriptor de activación (que ha debido ser previamente registrado).2005 -15- Protocolo de activación * El protocolo de activación: .CommandEnvironment Capítulo 12: RMI.class.Programación en Java. > El nombre de la clase del objeto. y que contiene: > El identificador de grupo (indica la JVM en que se ejecutará el objeto). Cursos de Verano de Málaga .Una referencia de fallo usa un identificador de activación y llama al activador (clase interna de RMI) para activar al objeto asociado. 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 .

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

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

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

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

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

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

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

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

Además: Capítulo 13: Ejecución de programas no Java. Cursos de Verano de Málaga .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. . JNI.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.Programación en Java.

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

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

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

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

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

Capítulo 13: Ejecución de programas no Java. if (exc) {/*Excepción producida*/} * La función nativa puede elevar excepciones con: newExcCls = (*env)->FindClass(env. . if (newExcCls == 0) { /* No se ha podido encontrar la clase */ return.Programación en Java. * La función nativa también puede corregir una excepción elevada con: (*env)->ExceptionClear(env). } (*env)->ThrowNew(env. "thrown from C code"). JNI. "java/lang/IllegalArgumentException"). Cursos de Verano de Málaga .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). newExcCls.

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

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

. Cursos de Verano de Málaga . Capítulo 14: Internacionalización. fechas y valores monetarios.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.Programación en Java.

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. además de otra información de formato.Un objeto de tipo MessageFormat se asocia con un Locale. Capítulo 14: Internacionalización. se detectaron 7 naves sobre el planeta Marte” * En otros idiomas. .Luego se le aplica un patrón que se encuentra en el ResourceBundle correspondiente. en inglés la hora iría antes que la fecha.ej. p.Por último.Programación en Java. * 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. éste mensaje se formatea con los parámetros que se quiera. almacenados en un array de Object. * Para solucionar este problema se hace uso de la clase MessageFormat. . . Cursos de Verano de Málaga . los datos pueden ir intercalados de otra forma. que permite expresar en un fichero de recursos una expresión completa: .

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

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

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

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. .Programación en Java. * 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.

println("Result: " + result).format(today). formatter = new SimpleDateFormat("EEE d MMM yy". de días. String result. etc. Cursos de Verano de Málaga . SimpleDateFormat formatter.Programación en Java.out. Capítulo 14: Internacionalización.out. result = formatter.2005 -9- Ejemplo de formato * El siguiente trozo de programa: Date today. today = new Date(). currentLocale). 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.toString()). . System.println("Locale: " + currentLocale. System.

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

E . System.out.toString()). DecimalFormat df = (DecimalFormat)nf. % ? $ un dígito un dígito.println(pattern + " " + output + " " + loc. si aparece duplicado se reemplaza por el símbolo monetario internacional.Programación en Java. * Los símbolos que se pueden usar en los patrones son: Symbol 0 # . 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.2005 -11- Patrones para números * También es posible utilizar patrones con los números. df.: NumberFormat nf = NumberFormat. Ej. .applyPattern(pattern). Cursos de Verano de Málaga . String output = df.format(value). . 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.getNumberInstance(loc).

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

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

Sign up to vote on this title
UsefulNot useful