P. 1
Total Java

Total Java

|Views: 22|Likes:
Publicado porMigueII

More info:

Published by: MigueII on May 14, 2013
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

03/23/2014

pdf

text

original

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.) RMI. El servidor La comunicación RMI. El applet Internet y BB. Servidor Servlets HTML y formularios Ciclo de vida de un servlet Clases para servlets Ejemplo de servlet Capítulo 12: RMI RMI.DD. Ejemplo Patrones para fechas y horas Ejemplo de formato Formato de números Patrones para números Ordenación Reglas de ordenación S G R Capítulo 15: Introducción a JSP Funcionamiento Instalación Componentes JSP . 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. Campos Acceso al objeto principal. JNI Ejecución de programas no Java JNI. El servidor (cont. Compilación del programa C Paso de parámetros jstring Arrays nativos Acceso al objeto principal.DD.Creación de tablas en HTML Internet y BB.

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. Depuración Manipulación del cuerpo Ejemplo de bucle Ámbito de objetos Etiquetas anidadas Bases de datos Etiquetas Java Descriptor de etiquetas .

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

como C++. con lo que una nueva ejecución de ese trozo de código será más rápida al no requerir una nueva traducción. ya que es pseudointerpretado. pero actualmente emplea optimizaciones que sólo lo hacen 2 veces más lento que C++.2005 -2- Características generales * Originalmente. * Java es seguro. dejan el código máquina traducido en un buffer para no tener que volver a traducirlo. a medida que van traduciendo el pseudocódigo a código máquina y lo van ejecutando. Java era muy lento.Programación en Java. . Con esto se pierde portabilidad. Éstos.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. Cursos de Verano de Málaga . . * ¿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. Capítulo 0: Introducción. * Para evitar aproximaciones: la lentitud hay dos . Impide accesos indebidos.

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

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

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

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

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

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

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

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

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

un objeto puede contener a muchos otros. . y así sucesivamente.O.. X Reenviar el mensaje a objetos que él mismo contiene. Composición p La forma más directa de usar una clase de objetos es creando objetos concretos. 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.2005 -6- Reutilización de código. P. Capítulo 1: Conceptos O. X Reenviar el mensaje a otros objetos externos. p Así. dentro del método asociado a éste puede: X Responder directamente. la clase de objetos Coche posee cuatro objetos de la clase Rueda. Cuando un objeto recibe un mensaje. de Java. Cursos de Verano de Málaga .ej.

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

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

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

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

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

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

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

p Java utiliza el concepto de excepción. Las excepciones se capturan en ciertos lugares bien definidos dentro del código Java. o bien lanzando una excepción. Cursos de Verano de Málaga . de Java. X Valores de retorno en las funciones que tienen que testarse. 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. el resultado son programas de difícil legibilidad. .2005 -14- Manejo de excepciones p En otros lenguajes el propio usuario tiene que controlar el control de errores. Una función puede acabar correctamente.Programación en Java.O. T Si el control es concienzudo.

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

de Java. así como el tipo de objeto que se quiere guardar/recuperar.Programación en Java. X Explícita: El programador debe indicar en el programa cuándo guardar y recuperar de disco.O. los objetos se almacenan en disco. Capítulo 1: Conceptos O. p Hay dos tipos de persistencia: X Implícita: Todos los objetos de una clase determinada se almacenan en disco. p Para ello. . p Es difícil de implementar debido a que los objetos pueden contener otros objetos (composición).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 . y en disco es necesario guardar referencias para mantener dichas conexiones.

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

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

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

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

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

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

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

* Hay implementaciones del motor de ejecución de Java.Programación en Java.2005 -6- Recolector de basura p Java se encarga de recoger todos los objetos que ya no estén siendo usados por nuestro programa. Cursos de Verano de Málaga . . * 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. * La incertidumbre sobre la recolección de basura hace que no se pueda emplear Java en sistemas en tiempo real. * La recolección de basura puede consumir bastante tiempo. Capítulo 2: Objetos en Java.

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

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

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

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

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

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

2005 -13- Operadores Java * Los operadores permitidos por Java son aproximadamente los mismos que los que posee C++. En estos casos. lo que ocurre es que el manejador lvalor referencia al mismo objeto que el manejador r-valor.<< >> >>> > < >= <= == != S G R && || & | ^ A > B? X : Y = (y asignaciones compuestas) * Cuando se asignan tipos primitivos. 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 . * No ocurre lo mismo cuando se trabaja con manejadores de objetos. Capítulo 2: Objetos en Java.Programación en Java.++ -* / % + . dado que no intervienen manejadores. lo que se hacen son copias de los datos concretos.

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

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

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

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

* while(expresión boolean) sentencia * do sentencia while(expresión boolean). break..Programación en Java. // Se sale de iteración_externa . 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_interna .. . continue label1. de flujo * La sentencia while tiene dos formatos.. break y continue pueden referenciar a un bucle más externo de aquél en el que se encuentran: label1: iteración_externa { iteración_interna { . break label1. * break y continue break se sale del bucle en el que se encuentra. continue. //Hace el siguiente ciclo de iteración_externa } } Capítulo 2: Objetos en Java. Cursos de Verano de Málaga .. continue acaba el ciclo actual y comienza el siguiente..2005 -18- Sentencias de ctrl. //Hace el siguiente ciclo de iteración_interna ..

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

-18-

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

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

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

-19-

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

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

S G R

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

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

-20-

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

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

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

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

-21-

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

S G R

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

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

-22-

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

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

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

Cursos de Verano de Málaga . Capítulo 4: Reutilización de código. Java testea en tiempo de compilación que los downcasting sean correctos. * 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.Programación en Java.2005 -24- Downcasting * Hacer upcasting es una operación segura. porque se tiene asegurado que un objeto hijo implementa como mínimo todas las operaciones de uno padre. 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. .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2.869e+24.4397e6). // en metros Planeta(double masa. 6.values() devuelve un array de objetos de tipo Estación. 2. } // Constante gravitacional universal (m 3 kg -1 s -2) public static final double G = 6.421e+23.976e+24.radio = radio. NEPTUNO (1. // en kilogramos private final double radio.303e+23.1492e7).67300E-11. Cursos de Verano de Málaga . 2. * El siguiente ejemplo ilustra cómo es posible asignar información (masa y radio) a los enumerados: public enum Planeta { MERCURIO (3.4746e7).2005 -13- Constructor de enumerados * La invocación Estación. TIERRA (5.Programación en Java. 6.137e6).9e+27. 6.5: Clases genéricas . this.024e+26. double gravedadEnSuperficie() { return G * masa / (radio * radio).masa = masa.37814e6). VENUS (4. SATURNO (5.688e+26.0518e6). 7. private final double masa. } } S G R Capítulo 5. } double pesoEnSuperficie(double otraMasa) { return otraMasa * gravedadEnSuperficie(). 1.0268e7). MARTE (6.27e+22. JÚPITER (1.5559e7).686e+25. PLUTÓN (1.3972e6). 3. double radio) { this. URANO (8.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

. .Empiezan por <TABLE> y acaban con </TABLE>. * 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.Cada dato de cada columna comienza por <TD>.Cada línea comienza con <TR>.Programación en Java.2005 -60- Creación de tablas en HTML * Las tablas en HTML siguen una estructura muy sencilla: . Capítulo 11: Programación Windows con Java. . .Cada cabecera de cada columna comienza por <TH>. Cursos de Verano de Málaga .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

df. DecimalFormat df = (DecimalFormat)nf. . * Los símbolos que se pueden usar en los patrones son: Symbol 0 # .format(value). . Ej. si aparece en un patrón se utilizará el separador decimal monetario en lugar del separador se puede usar cualquier carácter como prefijo o sufijo se emplea para entrecomillar caracteres especiales en un prefijo o sufijo X ' Capítulo 14: Internacionalización. si aparece duplicado se reemplaza por el símbolo monetario internacional.applyPattern(pattern).println(pattern + " " + output + " " + loc. 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.toString()). E . Cursos de Verano de Málaga .getNumberInstance(loc).Programación en Java.2005 -11- Patrones para números * También es posible utilizar patrones con los números.: NumberFormat nf = NumberFormat. % ? $ un dígito un dígito. String output = df.out. System.

Collator en_USCollator = Collator.length. . } } } } que puede ser llamado con los Collator: Collator fr_FRCollator = Collator. j < words. words[j]) > 0) { tmp = words[i].). Capítulo 14: Internacionalización. i < words. words[i] = words[j]. String[] words) { String tmp.getInstance(new Locale("fr".Programación en Java.. i++) { for (int j = i + 1.getInstance(new Locale("en". * Para ello se emplea la clase Collator.2005 -12- Ordenación * La mayoría de idiomas existente.. He aquí un ejemplo: public static void sortStrings(Collator collator. j++) { if (collator. Cursos de Verano de Málaga .length."US")). posee un conjunto de caracteres que extiende de alguna manera el del idioma inglés."FR")). 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(. * En estos idiomas. words[j] = tmp. for (int i = 0.compare(words[i].

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

You're Reading a Free Preview

Descarga
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->