Libro Java

Escuela de Ingeniería en Computación Universidad de La Serena. LECTURAS PARA PROGRAMACIÓN ORIENTADA A OBJETOS UTILIZAND

Views 50 Downloads 2 File size 3MB

Report DMCA / Copyright

DOWNLOAD FILE

Recommend stories

Citation preview

Escuela de Ingeniería en Computación Universidad de La Serena.

LECTURAS PARA PROGRAMACIÓN ORIENTADA A OBJETOS UTILIZANDO

Dr. Eric Jeltsch F. Agosto 2007.

INDICE I N D I C E ............................................................................................................................................................... 2 C A P I T U L O I .................................................................................................................................................... 4 Características de la Poo ................................................................................................................................... 10 C A P I T U L O II................................................................................................................................................. 25 Elementos Básicos en todo programa Java: Objetos y Métodos. ....................................................................... 28 Como construyo programas? ............................................................................................................................. 29 Primer encuentro con POO, el método System.out.println ............................................................................... 30 Cómo edito un programa?.................................................................................................................................. 30 Cómo ejecuto un programa Java ........................................................................................................................ 31 Java, una Plataforma Independiente .................................................................................................................. 33 Una visión de la plataforma JDK ....................................................................................................................... 35 Instalación de Java ............................................................................................................................................. 36 C A P I T U L O III ............................................................................................................................................... 42 Elementos del Lenguaje...................................................................................................................................... 42 Tipos de Datos y Strings ..................................................................................................................................... 42 Algunos Operadores ........................................................................................................................................... 43 Variables ............................................................................................................................................................ 43 Asignaciones....................................................................................................................................................... 45 Punto Flotante. ................................................................................................................................................... 46 Funciones Estándares ........................................................................................................................................ 47 Clases de I/O ...................................................................................................................................................... 49 ConsoleReader ................................................................................................................................................... 52 hsa.* ................................................................................................................................................................... 53 Swing .................................................................................................................................................................. 54 Strings................................................................................................................................................................. 57 C A P Í T U L O IV ................................................................................................................................................ 63 Decisiones (if)..................................................................................................................................................... 63 Ciclos .................................................................................................................................................................. 76 C A P I T U L O V ................................................................................................................................................. 86 Excepciones y Flujo de Datos (Exceptions y Streams) ...................................................................................... 86 Como leer archivos de texto ............................................................................................................................... 95 Leer de un Archivo de Texto ............................................................................................................................. 104 Escribiendo un Archivo de Texto ...................................................................................................................... 106 Archivos y Filtros. ............................................................................................................................................ 107 Excepciones y Flujo de Datos (Exceptions y Streams) .................................................................................... 110 Diagnostico de los errores en Expresiones y Variables ................................................................................... 111 Excepciones ...................................................................................................................................................... 114 Leer desde el teclado ........................................................................................................................................ 117 Como leer archivos de texto ............................................................................................................................. 120 Leer de un Archivo de Texto ............................................................................................................................. 128 Escribiendo un Archivo de Texto ...................................................................................................................... 131 Archivos y Filtros. ............................................................................................................................................ 132

Dr. Eric Jeltsch F.

Capítulo I: Programación Orientada a Objetos

C A P Í T U L O VI ............................................................................................................................................. 135 Programación Orientada a Objetos en Java .................................................................................................... 135 Clases y Objetos ............................................................................................................................................... 136 Instancias de una Clase .................................................................................................................................... 137 Constructores ................................................................................................................................................... 138 Variables en la clase ........................................................................................................................................ 139 Clase como Tipo ............................................................................................................................................... 139 Expresiones para instanciar ............................................................................................................................. 140 Métodos Instanciados ....................................................................................................................................... 140 La palabra clave this ........................................................................................................................................ 141 Métodos en las Clases ...................................................................................................................................... 142 Implementando Estructuras de Datos .............................................................................................................. 142 Listas ................................................................................................................................................................ 142 Arboles AVL ..................................................................................................................................................... 144 Jerarquia de Clases .......................................................................................................................................... 157 Herencia ........................................................................................................................................................... 158 Jerarquia de clases en Java.............................................................................................................................. 160 Herencia y Constructores ................................................................................................................................. 161 Dynamic Binding .............................................................................................................................................. 162 Polimorfismo .................................................................................................................................................... 162 Sobreescritura de métodos ............................................................................................................................... 163 Clases Abstractas y Métodos Abstractos .......................................................................................................... 163 Interfaces .......................................................................................................................................................... 165 Paquetes ........................................................................................................................................................... 168 Declaración import ......................................................................................................................................... 168 Java-Paquetes Estandar ................................................................................................................................... 169 Programación Orientada a Objetos comparada con la Programación de Procesos y programación orientada a eventos. ............................................................................................................................................................. 169 C A P I T U L O VII ............................................................................................................................................ 181 Eventos (Events) ............................................................................................................................................... 181 Eventos ............................................................................................................................................................. 182 GUI Minimo-Minimorum: ............................................................................................................................... 186 Estuctura de una Aplicación Swing. ................................................................................................................. 189 C A P Í T U L O VIII. .......................................................................................................................................... 203 Swing ................................................................................................................................................................ 203 C A P Í T U L O IX ............................................................................................................................................. 221 Swing: Eventos de Ratón y Movimientos del Ratón ......................................................................................... 221 C A P I T U L O X .............................................................................................................................................. 232 GUI Avanzado (con Swing) .............................................................................................................................. 232 C A P Í T U L O XI .............................................................................................................................................. 245 GUI Avanzado (con Swing) .............................................................................................................................. 245

Ingeniería en Computación, Universidad de La Serena

3

CAPITULO I PROGRAMACIÓN ORIENTADA A OBJETOS La programación orientada a objetos proporciona una forma de ver los programas en función de los datos y los métodos que operan sobre ellos. En la programación orientada a objetos, la atención se aleja de las funciones y se acerca a las cosas (objetos) que componen el programa. Las diferencias básicas entre la programación orientada a objetos y el enfoque de procesos, eventos u aspectos, pueden agruparse en cuatro principios básicos: abstracción, encapsular, herencia y polimorfismo. Abstracción es el proceso de ignorar temporalmente los detalles subyacentes al objeto, para centrar la atención en el problema u objeto y así extraer sus características esenciales. Por ejemplo, si se consideran los neumáticos de un auto, el neumático abstracto puede tener una marca, tamaño precio y una cantidad ideal de aire. Estas características se aplican a todos los neumáticos. Al utilizar la abstracción es posible centrar la atención sobre estas características (comunes), en lugar de hacerlo sobre los detalles de un tipo específico de neumático. Encapsular es el proceso de agrupar la información abstraída del objeto con las operaciones (métodos) que un programa puede realizar sobre los datos. Por ejemplo, una clase es el encapsulado de los datos y métodos de un objeto. Herencia es un marco en el cual se pueden crear nuevas clases al introducir nuevas características o cambios a clases ya existentes. La herencia libera al programador de la tarea de reescribir funciones cuando se deben hacer pequeños cambios. Finalmente, el Polimorfismo es la habilidad que tiene un objeto de tomar diferentes formas. El prefijo poli significa “muchas”; morfismo “formas”. Por ejemplo, en un programa, un objeto polimorfo que represente un teléfono puede cambiar de forma para representar un teléfono de tonos, un teléfono de pulsos o incluso un teléfono celular. Como puede notar algunos conceptos de la POO son análogos a los métodos de programación convencional, por ejemplo. Un método es como un procedimiento porque ambos contienen instrucciones de procesamiento. Las variables de clase y modelo se correlacionan a los datos de la programación tradicional. Los métodos y datos son diferentes porque los procedimientos no están encapsulados normalmente con los datos que manipulan. Una clase es como un tipo abstracto de datos, aunque para la POO, el proceso de escribir no se revela fuera de la clase. La herencia no tiene analogía inmediata en la programación convencional. El paso de mensajes reemplaza a las llamadas de función como método principal de control en los sistemas orientados a objeto. Con las llamadas de funciones, los valores se presentan y el control regresa a la función que efectúa la llamada. Por el contrario, los objetos entran en acción gracias a los mensajes, y el control está distribuido. Considere como ejemplo, una entidad bancaria. En ella identificamos entidades que son cuentas: cuenta_del_cliente1, cuenta_del_cliente2, etc. Al mismo tiempo, una cuenta puede verse como un objeto que tiene atributos. Por ejemplo, nombre, número_de_cuenta y saldo, y

Dr. Eric Jeltsch F.

Capítulo I: Programación Orientada a Objetos

un conjunto de métodos como IngresarDinero, RetirarDinero, AbonarIntereses, SaldoActual, Transferencia etc. En el caso de una transferencia, se podría escribir por ejemplo, cuenta_del_clientel.Transferencia(cuenta_del_cliente2);

cuyo significado sería que, Transferencia es el mensaje que el objeto cuenta_del_cliente2 envía al objeto cuenta_del_cliente1, solicitando le sea hecha una transferencia, siendo la respuesta a tal mensaje la ejecución del método Transferencia. Trabajando a este nivel de abstracción, manipular una entidad bancaria resultará algo muy sencillo.

Mecanismos Básicos de la Poo Objetos Un programa OO se compone solamente de objetos, entendiendo por objeto una encapsulación genérica de propiedades o datos y de los métodos para manipularlos. Por ejemplo una ventana de Windows es un objeto, en donde, el color de fondo, la altura, la anchura son propiedades, mientras que las rutinas (transparentes al usuario), que permiten maximizar o minimizar la ventana son métodos. Mensajes Cuando se ejecuta un programa OO los objetos están recibiendo, interpretando y respondiendo a mensajes de otros objetos. De manera que en la POO un mensaje está asociado con un método. Si continuamos con el ejemplo de la ventana de Windows, digamos que cuando un usuario desea maximizar una ventana, lo que hace es pulsar el botón de la misma que realiza esa acción, esto es que Windows envíe un mensaje a la ventana para indicarle que tiene que maximizarse, y como respuesta a este mensaje se ejecutará el método programado para ese fin. Métodos Un método se implementa en una clase de objetos y determina cómo tiene que actuar el objeto para cuando recibe el mensaje vinculado con ese método. De la misma manera un método puede también enviar mensajes a otros objetos solicitando una acción o información. Cuando se diseña una clase de objetos, la estructura más interna del objeto se oculta a los usuarios que lo vayan a utilizar, manteniendo como única conexión con el exterior, los mensajes. Esto es, los datos que están dentro de un objeto solamente podrán ser manipulados por los métodos asociados al propio objeto. Según lo expuesto, podemos decir que la ejecución de un programa orientado a objetos realiza fundamentalmente tres cosas: 1. Crea los objetos necesarios. 2. Los mensajes enviados a unos y a otros objetos dan lugar a que se procese internamente la información. 3. Finalmente, cuando los objetos no son necesarios, son borrados, liberándose la memoria ocupada por los mismos.

Ingeniería en Computación, Universidad de La Serena

5

Dr. Eric Jeltsch F.

Capítulo I: Programación Orientada a Objetos

Clases Una clase es un tipo de objetos definido por el usuario. Una clase equivale a la generalización de un tipo específico de objetos. Por ejemplo, Empleado. Empleado

No obstante esta clase puede expandirse para incluir atributos, en este caso apellido, nombre, rut y sexo. Para tal efecto, todos los atributos son definidos en la clase a través de variables, es así como la clase adquiere la siguiente forma: Código Java class Empleado { String apellido; String nombre; int rut; boolean esFemenino; }

UML Empleado apellido: String nombre: String rut: int esFemenino: boolean

Además, si Ud. desea puede definir que los atributos tengan algunas propiedades, tales como privado (-), público(+) o protegido(#). En tal caso queda, Código Java public class Empleado { private String apellido; private String nombre; private int rut; private boolean esFemenino; }

UML Empleado -

apellido: String nombre: String rut: int esFemenino: boolean

Por otro lado cabe preguntarse ¿que deseo hacer con la clase Empleado?. Por ejemplo se desea registrar horas de trabajo, horas extraordinarias, sueldo, viáticos, u otros. En tal caso, se deben implementar ciertos métodos que realicen ésta tarea. Según lo expuesto hasta ahora, un objeto contiene, por una parte, atributos que definen su estado, y por otra, operaciones que definen su comportamiento. También sabemos que un objeto es la representación concreta y específica de una clase. ¿Cómo se escribe una clase de objetos? Como ejemplo, podemos crear una clase PC1. Ejemplo 1. public class PC1 { String marca; String procesador; String pantalla; boolean PC1_Encendido; boolean presentacion; }

Ingeniería en Computación, Universidad de La Serena

6

Dr. Eric Jeltsch F.

Capítulo I: Programación Orientada a Objetos

en esta oportunidad se han definido 5 atributos. Veamos ahora, desde un punto de vista práctico, que acciones serían convenientes considerar, por ejemplo, ponerse en marcha, apagarse, cargar una aplicación, desactivar algún proceso o activar otro, etc. Ahora para implementar este comportamiento hay que crear métodos. Los métodos son rutinas de código definidas dentro de la clase, que se ejecutan en respuesta a alguna acción tomada desde dentro de un objeto de esa clase o desde otro objeto de la misma o de otra clase, recuerde que los objetos se comunican mediante mensajes. Ejemplo 2. public class PC1 { String marca; String procesador; String pantalla; boolean PC1_Encendido; boolean presentación; //método de la clase void EncenderPC1() { if (PC1_Encendido == true) // si está encendido... System.out.println("El PC ya está encendido."); else // si no está encendido, encenderlo. { PC1_Encendido = true; System.out.println("El PC se ha encendido."); } } //método de la clase void Estado() { System.out.println("\nEstado del PC:" + "\nMarca " + marca + "\nProcesador " + procesador + "\nPantalla " + pantalla + "\n"); if (PC1_Encendido == true) // si el ordenador está encendido... System.out.println("El PC está encendido."); else // si no está encendido... System.out.println("El PC está apagado."); } //método de la clase, llamada clase principal public static void main (String[] args) { PC1 miPC1 = new PC1(); miPC1.marca = "Dell"; miPC1.procesador = "Intel Pentium"; miPC1.pantalla = "AOC"; miPC1.EncenderPC1(); miPC1.Estado(); } }

Ingeniería en Computación, Universidad de La Serena

7

Dr. Eric Jeltsch F.

Capítulo I: Programación Orientada a Objetos

Como se puede observar un método consta de su nombre precedido por el tipo del valor que devuelve cuando finalice su ejecución (la palabra reservada void indica que el método no devuelve ningún valor y seguido por una lista de parámetros separados por comas y encerrados entre paréntesis (en el ejemplo, no hay parámetros). Los paréntesis indican a Java que el identificador EncenderPC1() se refiere a un método y no a un atributo. A continuación se escribe el cuerpo del método encerrado entre {y}. Usted ya conoce algunos métodos, llamados en otros contextos funciones; seguro que conoce la función logaritmo que devuelve un valor real correspondiente al logaritmo del valor pasado como argumento. Otro método es Estado()que visualiza los atributos específicos de un objeto. Finalmente para poder crear objetos de esta clase y trabajar con ellos, tendrá que añadir a esta clase el método main(), tal como se hizo aquí, o bien escribir un programa principal, tal como se muestra a continuación, en donde MiPC.java esta en un directorio y el archivo PC2.class en el mismo, de otra manera no se entendera el llamado que se hace. A continuación se visualiza un típico mensaje de error de esta naturaleza.

C:\Documents and Settings\usuario\Escritorio\POO\curso_poo_2006\MiPC.java:5: cannot resolve symbol symbol : class PC2 location: class MiPC PC2 miPC2 = new PC2(); ^ C:\Documents and Settings\usuario\Escritorio\POO\curso_poo_2006\MiPC.java:5: cannot resolve symbol symbol : class PC2 location: class MiPC PC2 miPC2 = new PC2(); ^ 2 errors

En resumen, Herramienta las bibliotecas de clases y los marcos proporcionan una excelente completada con código de salidaestructurales 1 plataforma para el desarrollo de las aplicaciones orientadas a objetos y la reutilización del código.

Ingeniería en Computación, Universidad de La Serena

8

Dr. Eric Jeltsch F.

Capítulo I: Programación Orientada a Objetos

Ejemplo 3. public class MiPC { public static void main (String[] args) PC2 miPC2 = new PC2(); miPC2.marca = "Dell"; miPC2.procesador = "Intel Pentium"; miPC2.pantalla = "AOC"; miPC2.EncenderPC2(); miPC2.Estado(); } } //método de la clase class PC2{ String marca; String procesador; String pantalla; boolean PC2_Encendido; boolean presentación;

{

//método de la clase void EncenderPC2() { if (PC2_Encendido == true) // si está encendido... System.out.println("El ordenador ya está encendido."); else // si no está encendido, encenderlo. { PC2_Encendido = true; System.out.println("El ordenador se ha encendido."); } } //método de la clase void Estado() { System.out.println("\nEstado del ordenador:" + "\nMarca " + marca + "\nProcesador " + procesador + "\nPantalla " + pantalla + "\n"); if (PC2_Encendido == true) // si el ordenador está encendido... System.out.println("El ordenador está encendido."); else // si no está encendido... System.out.println("El ordenador está apagado."); } }

Ingeniería en Computación, Universidad de La Serena

9

Dr. Eric Jeltsch F.

Capítulo I: Programación Orientada a Objetos

Características de la Poo Las características fundamentales de la POO son: encapsulación, herencia, abstracción, y polimorfismo.  Encapsulamiento La encapsulación es el término formal que describe el conjunto de métodos y datos dentro de un objeto de forma que el acceso a los datos se permite solamente a través de los métodos del objeto. Esta característica permite entonces ver un objeto como una caja negra en la que se ha introducido de alguna manera toda la información relacionada con dicho objeto, permitiendo manipular los objetos como unidades básicas, permaneciendo oculta su estructura interna. Generalmente los atributos de una clase de objetos se declaran privados, estando así oculto para otras clases, siendo posible el acceso a los mismos únicamente a través de los métodos públicos de dicha clase. El mecanismo de ocultación de miembros se conoce en la POO como encapsulación. El nivel de protección predeterminado para un miembro de una clase es el de package (paquete), habiendo otros tales como, public, private y protected. Ejemplo 4. /** * Conversión de grados centígrados a fahrenheit: * F = 9/5 * C + 32 */ import java.lang.System;

// importar la clase System

public class CApGrados { // Definición de constantes final static int limInferior = -30; final static int limSuperior = 100; final static int incremento = 6; public static void main(String[] args) // Declaración de variables CGrados grados = new CGrados(); int gradosCent = limInferior; float gradosFahr = 0;

{

while (gradosCent 1) { System.out.println("error: comision debe estar entre 0 y 1"); this.razon = 0; } else { this.razon = razon; } // end if } // end constructor /********************************************************************** * Constructor: Crea un salesperson quien recibe comision solamente * (no pago por horas), dar el nombre, job titulo y razon de la comision. * * Parametros: * nombre: nombre del empleado * titulo: el job titulo para el empleado * razon: razon de comision del empleado, entre 0 y 1. *********************************************************************/ public Salesperson(String nombre, String titulo, double razon) { this(nombre, titulo, 0, razon); } // end constructor /********************************************************************** * Pago al salesperson por viaje, de acuerdo a la razon de comision. * * Parametro: monto para el viaje. *********************************************************************/ public void pagoViaje(double montoViaje) { pagoO += razon * montoViaje; } // end pagoViaje /********************************************************************** * Crea una representacion String para Salesperson, incluyendo nombre, * job titulo, jornal, pagoO, y razon de comision. * * Return valor: representacion string *********************************************************************/ public String aString() { return "(Salesperson) " + super.aString() + ", razon de comision: " + razon; } // end aString } // end class Salesperson

Algo que se debe tener cuenta respecto al vocabulario es que la clase Empleado es la superclase(o clase padre), Salesperson es una subclase (o clase derivada). Se dice también que la clase Salesperson extiende a la clase Empleado. Salesperson hereda variables y métodos de la clase Empleado. Salesperson es una clase derivada, que deriva de la clase Empleado.

Ingeniería en Computación, Universidad de La Serena

21

Dr. Eric Jeltsch F.

Capítulo I: Programación Orientada a Objetos

Una clase hija o derivada hereda todas las variables y métodos del padre, pero NO constructores, esto significa que cada clase necesita de un constructor o constructores propios. Por otra parte, un mejor camino para evitar duplicidad en la codificación de la inicialización es considerar el método super(), considerada como superclase. La declaración super(nombre, titulo, jornal);

dice que llama al constructor de la superclase, es decir Empleado. Invocar a super(), se debe hacerse en el constructor en la primera llamada, para que pueda asumirlo. Otra clase derivada podría ser, si es que sigue el juego de la organización, los empleados ejecutivos, los que pueden recibir bonos de productividad, los que no están basados en horas necesariamente. Por ejemplo Ejemplo 13. /************************************************************************ * clase para empleado ejecutivo. Obtiene jornal plus bonos. ***********************************************************************/ public class Ejecutivo extends Empleado { /********************************************************************** * Constructor: Crea un ejecutivo dando nombre, job titulo, y jornal. * Parametros: * nombre: nombre del empleado * titulo: el job titulo del empleado * jornal: jornal del empleado *********************************************************************/ public Ejecutivo(String nombre, String titulo, double jornal) { /* Note que TODOS estos constructores hacen esto para llamar a la clase padreconstructor con los mismos parametros. Este constructor es necesario ,pues clases hijas no heredan constructores, por eso la declaracion.*/ super(nombre, titulo, jornal); } // end constructor /********************************************************************** * Pago de bonos al ejecutivo. * * Parametro: monto del bono *********************************************************************/ public void pagoBono(double bono) { pagoO += bono; } // end pagoBono /********************************************************************** * Crea una representación String de Ejecutivo, incluyendo nombre, * job titulo, jornal y pago. * * Return valor: representacion string *********************************************************************/ public String aString() { return "(Ejecutivo) " + super.aString(); } // end aString } // end class Ejecutivo

Ingeniería en Computación, Universidad de La Serena

22

Dr. Eric Jeltsch F.

Capítulo I: Programación Orientada a Objetos

Veamos a continuación una clase principal que servirá para testear la clase Empleado sus métodos y las subclases. Ejemplo 14. /************************************************************************ * Un programa para testear la clase Empleado y sus subclases. * ***********************************************************************/ public class EmpleadoTest { // Metodo principal main: Crea varios empleados de diferentes tipos y testeamos // los diferentes métodos. public static void main(String noUsado[]) { // un empleado "normal" , pago $2. 250/hora, sin sobretiempo Empleado ambler = new Empleado("Ambler", "agente", 2.250); ambler.pago(8); ambler.pago(10); // total horas son 18, pago es de 2.250 * 18 = $40.500. System.out.println("monto a pagar a ambler: $" + ambler.monto_a_Pagar()); // chequear el metodo cero ambler.cero(); ambler.pago(8); // pago es de 8 * 2.250 = 18.000. System.out.println("monto a pagar a ambler: $" + ambler.monto_a_Pagar()); // un ejecutivo recibe $3.000/hora, sin sobretiempo pero puede recibir bonos Ejecutivo perez = new Ejecutivo("perez", "director", 3.000); perez.pago(10); perez.pago(10); perez.pagoBono(10); // pago debería ser 2.000 * 3.000 + 10.000 = $70.000 System.out.println("montoa a pagar a perez: $" + perez.monto_a_Pagar()); // un vendedor viajero, recibe $1.000/hora plus 20% comision. Sin bonos o sobretiempo Salesperson castillo = new Salesperson("castillo", "salesperson", 1.000, .2); castillo.pago(10); castillo.pagoViaje(40); // pago debería ser 1.000 * 1.000 + .2 * 40.000 = $18.000. System.out.println("montoa pagar a castillo: $" + castillo.monto_a_Pagar()); // Demo para el metodo igual System.out.println(); Empleado emp1 = new Empleado("Mario", "ingeniero", 3.000); Empleado emp2 = new Empleado("Maria", "programador", 3.000); System.out.println(emp1.igual(emp2)); // false Salesperson emp3 = new Salesperson("Mario", "ingeniero", 3.000, .1); System.out.println(emp1.igual(emp3)); // true } // end main } // end class EmpleadoTest

Ingeniería en Computación, Universidad de La Serena

23

Dr. Eric Jeltsch F.

Capítulo I: Programación Orientada a Objetos

De la misma forma como se ha realizado aquí podría construirse una nueva clase que resulte ser una extensión de Empleado. Por ejemplo, considerar la situación de que algunos Empleados reciben pago extra por sobretiempo, en tal caso considere el cálculo del sueldo con sobretiempo. Por ejemplo “incremento de horas > 8 se paga 50% sino se paga como antes,” etc.

Ingeniería en Computación, Universidad de La Serena

24

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

C A P I T U L O II FUNDAMENTOS El libro Java How To Program (Deitel & Deitel 3Ed.) comienza con un capítulo que describe las ideas básicas de computación, programas, y lenguajes de programación, este es un buen libro guía. Por otra parte, el libro de Cay S. Horstmann, Core Java 2, Volumen I, es un libro para personas que ya se manejan en Java. En la práctica siempre nos encontraremos con libros que de una u otra manera tienen enfoques distintos. Este material tampoco es la excepción y en nuestro caso está orientado a los alumnos que en cierto modo han programado en algún lenguaje de programación y poseen un conocimiento de las herramientas básicas de la programación, no obstante lo anterior, me he esmerado en mostrar en cada capítulo las herramientas que deberían conocer. No pretendo ser exhaustivo en el tema, sino tan sólo fijar ciertos estándares de conocimientos no importando el orden usual, es decir en este sentido no comienzo definiendo los tipos de datos, luego operadores, como usualmente se hace, sino que con el tipo de datos enteros voy utilizando las asignaciones, operadores, definición de funciones en diversas aplicaciones, ya que Ud. se supone que aprendió C, y además curso Estructuras de Datos. El lenguaje Java que estaremos usando es uno de los más recientes lenguajes de programación de alto nivel, la primera versión apareció en 1995, y Java2 versión 1.4 que estaremos usando sólo se libero el año 2001. Java nació bajo el alero de una gran empresa de hardware y de desarrollo de tecnologías, como es la empresa SUN Microsystems, siendo uno de los referentes más importantes en el tema. Hoy en día ya se cuenta con la versión 1.5, apropiada para la programación genérica. El programa en Java es traducido por el compilador que es un programa en un lenguaje llamado bytecode que es similar al código de máquina pero es independiente de cualquier sistema en particular. El bytecode producido por compilador e interpretado por la máquina virtual de Java (JVM) se llama código del objeto. Fig. 1 muestra la forma en que se realizan los procesos.

Figura 1.

Los 3 procesos: escribir un programa, compilarlo, y ejecutarlo.

Ingeniería en Computación, Universidad de La Seren

25

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

Existe un número de herramientas disponibles para compilar y ejecutar programas Java. Para este curso utilizaremos la versión liberada y disponible en el sitio Web, llamada Software Development Kit (SDK), que puede ser bajada en forma gratuita de la dirección, http://java.sun.com/j2se/

Un primer programa en Java Aquí mostramos algunos programas, su compilación y ejecución. public class Hola { /* Escribe un mensaje sobre la pantalla. */ public static void main(String[] args) { System.out.println(Hola La Serena!); }

declaraciones.

}

Todo programa en Java contiene declaraciones. Cada declaración describe algunas operaciones que el computador lleva a cabo. Por ejemplo, con la línea System.out.println(Hola La Serena!);

se pretende desplegar el mensaje: Hola La Serena! en la pantalla de la consola. Java tiene varios caminos para escribir mensajes en la pantalla o desplegarlos en páginas Web. En este caso, usamos una parte de un programa(o método) llamado System.out.println. El resultado será que el mensaje sea desplegado en la pantalla DOS Window. Aquí se muestra el programa con dos declaraciones. Las dos declaraciones son escritas en bold face. (Es solo para resaltar, no use bold face en el programa actual, Java no acepta formatos ni fuentes extrañas.) public class Hola1 { /* Escribe un mensaje sobre la pantalla. */ public static void main(String[] args) { System.out.println(Hola La Serena!); System.out.println(Nos vemos.); } }

La salida será: Hola La Serena! en una línea, y en la próxima se verá Nos vemos. Notar la forma clásica del programa modelo, en donde las declaraciones están entre{ }.

Ingeniería en Computación, Universidad de La Seren

26

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

public class Hola { /* Escribir un mensaje simple. */ public static void main(String[] args) { Declaraciones

} }

La Fig. 2, muestra el efecto que se genera sobre el archivo fuente Hola_Alumnos tras de realizar la compilación (con el comando javac). Ud. podrá notar la generación de dos nuevos archivos con extensión .class (conteniendo bytecode).

Fig. 2: Generación de archivos .class en bytecode

Ingeniería en Computación, Universidad de La Seren

27

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

Elementos Básicos en todo programa Java: Objetos y Métodos. Por ejemplo, si escribe un programa para alguna organización que posee un gran registro de personal deberá considerar un registro de personas y categorías, siendo probable entonces que defina “Empleados”, “Secretarias” u otros, estos elementos en la Programación Orientada a Objetos se llaman objetos. Al mismo tiempo se necesitan, para que el programa pueda decidir, que operaciones se pueden llevar a cabo sobre los objetos antes definidos. Por ejemplo, actualizar la lista de Empleados, o desplegar algún reporter de alguna información registrada sobre el Personal. Las operaciones que Ud. puede ejecutar sobre los objetos se llaman métodos. Cuando Ud. defina un nuevo tipo de objetos deberá definir también sus métodos. Incluso en las declaraciones de Java ya está implícito este concepto. Por ejemplo, la declaración System.out.println denota el método llamado println que pertenece al objeto llamado System.out. System.out es un objeto cuya labor es recibir la información para luego desplegarla sobre la pantalla. El método println es la operación usada para emisión de mensajes. Así la declaración System.out.println(Hola amigos!);

usa el método println para enviar el mensaje Hola amigos! al objeto System.out (el que lo despliega en pantalla). Todo objeto pertenece a una clase la cual especifica los métodos y objetos que allí habitan. La potencialidad, en la práctica del lenguaje Java viene dada por su biblioteca de clases. Entre las cuales destacan 2 paquetes (packages) de propósito general como son java.io y java.lang. Por ejemplo, la biblioteca de Java proporciona 3 flujos estándar, manejados por la clase System del paquete java.lang, que son automáticamente abiertos cuando se inicia un programa y cerrado para cuando finaliza.   

System.in, referencia a la entrada estándar del sistema que normalmente coincide con el teclado. Se utiliza para leer datos introducidos por el usuario. System.out, referencia a la salida estándar del sistema que normalmente es el monitor. Se utiliza para mostrar datos al usuario. System.err, referencia a la salida estándar de error del sistema, que normalmente es el monitor. Se utiliza para mostrar mensajes de error al usuario.

Java en general nos ofrece la libertad de crear nuestras propias clases, métodos, objetos y paquetes, pero por lo mismo debemos conocer al menos la biblioteca de clases de Java, pues no en vano la librería de Java esta compuesta enteramente de clases. Existen algunas clases que consisten de un número de métodos stand-alone, es decir que no pertenecen a algún objeto en particular, a estos le llamaremos métodos static. No todos los datos utilizados en los programas Java son objetos, es así por ejemplo los tipos de datos simples, tales como integers y números floating-point son considerados en forma diferente. Ellos son llamados tipos datos primitivos, porque están integrados en el sistema. Sin embargo, no confundirse porque la biblioteca de Java proporciona las clases: Byte, Ingeniería en Computación, Universidad de La Seren

28

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

Character, Short, Integer, Long, Float, Double y Boolean, para encapsular cada uno de los tipos expuestos. Vea http://java.sun.com/docs/books/tutorial/java/data/numbers.html Como construyo programas? En la última sección explicamos que un programa Java consiste de un número de clases. El ejemplo anterior es una muestra de ello pero muy simple. En todo caso, todo programa consiste de una clase que contiene justamente un método estático. Todo lenguaje de programación hace uso de métodos pero usualmente bajo nombres diferentes, por ejemplo, „procedure‟ o „function‟ son frecuentes en Pascal o C. En Java se conocen como métodos. Aquí está el programa anterior usando métodos con una indentación apropiada para entender cuando y donde termina una declaración 1. /* Escribir un mensaje en pantalla. */ 2. public static void main(String[] args) 3. { System.out.println(Hola, amigo! ); 4. System.out.println(Luego nos vemos. ); 5. }

Comentarios: 1.

/* Escribir un mensaje en pantalla. */

Esto es un comentario que describe lo que el programa hace. Puede usar también //, en el caso que sea solamente una línea. 2.

public static void main(String[] args)

Este es el encabezado del método principal. Todo método tiene un nombre, en este caso es la palabra main (principal) que viene justamente antes del paréntesis. Las palabras public, static y void son llamadas por el compilador Java para cuando el método deba ser usado. Esto lo explicaremos después. La parte String[] args, describe la información que esta puesta a disposición, llamada a los parámetros. 3-5. {

System.out.println(Hola, amigos! ); System.out.println(Luego nos vemos. );

}

es el cuerpo del método. Todo programa consiste de un número de clases. En los ejemplos anteriores, los programas tienen solamente una clase llamada Hola. Posible de darse cuenta de esto por el encabezado public class Hola

Ingeniería en Computación, Universidad de La Seren

29

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

Primer encuentro con POO, el método System.out.println System.out.println

es nuestro primer ejemplo de un método que pertenece a la librería de Java, la que contiene métodos que controlan más aspectos, tales como desplegar un string de caracteres en DOS window. Este es un tipo muy simple de tratamiento de ventanas. El nombre println es la abreviación de „print line‟, „imprime línea.‟. Para ver otra sutil diferencia reemplace println por print. Así una declaración del tipo System.out.print(Hola, amigo!\nLuego nos vemos.\n)

imprime Hola, amigo!, moviendo el cursor al comienzo de la siguiente línea, en donde imprimirá Luego nos vemos., y mueve el cursor a la partida de la siguiente línea. La declaración anterior tiene el mismo efecto que las dos declaraciones siguientes. System.out.println(Hola, amigo! ); System.out.println(Luego nos vemos. )

Cómo edito un programa? Cuando escriba un programa, tenga especial cuidado al usar System.out.println. Para escribir un mensaje sobre la pantalla termine con un semicolon, si lo olvida el compilador detectara un error y abortara la compilación de su programa, enviando un mensaje de error compiler error (o syntax error, o parse error). Java es un lenguaje sensitivo, es decir distingue entre mayúsculas y minúsculas, por ejemplo CLASS o Class al comienzo del programa. Ud. debe siempre tipear class, que es la palabra reservada.

Ingeniería en Computación, Universidad de La Seren

30

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

Cuántos errores de sintaxis visualiza en este programa? public Clase Holas { /* Escribir un mensaje en la pantalla. public static viod Main(string[] args) { System.out,println('Hola, amigo!); System.out.printline(Luego nos vemos.); ) }

Otro problema común son los espacios en blanco, por ejemplo, public c lass H ola{public static void main(String[] args){System.out.println(Hola, amigo!);System. out.println(Luego nos vemos.);}} }

Cómo ejecuto un programa Java Supongamos que ejecutamos el ejemplo. public class Hola { /* Escribir un mensaje en pantalla. */ public static void main(String[] args) { System.out.println(Hola, amigo!); } }

Se supone que Ud. cuenta con un editor de texto como NotePad, TextPad o JPadPro 1. 2. 3. 4. 5. 6.

Editar el programa y guardarlo en un archivo llamado Hola.java. Si su programa consta de una sola clase guárdelo con el mismo nombre de la clase seguido de la extensión .java. En nuestro caso guárdelo en Hola.java Para compilar escriba el comando en la consola DOS > javac Hola.java Si no tiene problemas de compilación u errores sintácticos el compilador genera una versión en bytecode en el archivo con el nombre Hola.class. Obtenga ahora una Java Virtual Machine (JVM) que viene incorporada con la distribución para ejecutar el bytecode compilado del programa que esta en Hola.class , esto lo logra escribiendo >java Hola

Ingeniería en Computación, Universidad de La Seren

31

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

Fig. 3. Los tres procesos: escribir el archivo del programa, compilar para producir el archivo .class, y ejecutar el archivo class.

Existen dos formas de correr un archivo ejecutable, ellas son llamadas Aplicaciones Java y Applet Java.  

Una Aplicación Java, son programas que pueden ser ejecutados invocando al interprete Java, desde la línea de comando. Un Applet es un programa Java que es incrustado en páginas Web y ejecutados por un browser que soporta a Java. Hoy en día los Browser, tales como Explorer, Netscape, lo poseen. Así se visualizan ambos, note la diferencia. public class TrivialAplicacion { public static void main(String[] args) { System.out.println("Hola,amigos.!"); } } import java.awt.*; import java.applet.Applet; public class TrivialApplet extends Applet { public void paint(Graphics g) { g.drawString("Hola,amigos.!", 20, 20); } } código HTML

Ingeniería en Computación, Universidad de La Seren

32

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

Java, una Plataforma Independiente Compilar

Fig 4. La máquina virtual JVM, en acción

Para traducir un programa escrito en un lenguaje de alto nivel (programa fuente) a lenguaje máquina se utiliza un programa llamado compilador. Este programa tomará como datos nuestro programa escrito en lenguaje de alto nivel y dará como resultado el mismo programa pero escrito en lenguaje máquina (en java bytecode), programa que ya puede ejecutar directa o indirectamente el computador. Por ejemplo, un programa escrito en el lenguaje C necesita del compilador C para poder ser traducido. Posteriormente el programa traducido podrá ser ejecutado directamente por el computador. En cambio, para traducir un programa escrito en el lenguaje Java necesita del compilador Java; en este caso, el lenguaje máquina no corresponde al del computador sino al de una máquina ficticia, denominada máquina virtual Java(JVM, Java Virtual Machine), que será puesta en marcha por el computador para ejecutar el programa. JVM (Máquina Virtual) ¿Qué es una máquina virtual?. Una máquina que no existe físicamente sino que es simulada en un computador por un programa. ¿Por qué utilizar una máquina virtual? Porque, por tratarse de un programa, es muy fácil instalarla en cualquier computador, basta con copiar ese programa en su disco duro, por ejemplo. Y, ¿qué ventajas reporta? Pues, en el caso de Java, que un programa escrito en este lenguaje y compilado, puede ser ejecutado en cualquier computador que tenga instalada esa máquina virtual, de hecho ya todos los sistemas operativos cuentan con este soporte, vea Fig. 4. Esta solución hace posible que cualquier computador pueda ejecutar un programa escrito en Java independiente de la plataforma que utilice. Ingeniería en Computación, Universidad de La Seren

33

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

Por otra parte, a diferencia de un compilador, un intérprete no genera un programa escrito en lenguaje máquina a partir del programa fuente, sino que efectúa la traducción y ejecución simultáneamente para cada una de las sentencias del programa. Por ejemplo, un programa escrito en el lenguaje javaScript necesita el intérprete que por lo general está en los browser (Netscape, Explorer, etc.) para ser ejecutado. Durante la ejecución de cada una de las sentencias del programa, ocurre simultáneamente la traducción. Notar que, a diferencia de un compilador, un intérprete verifica cada línea del programa cuando se escribe, lo que facilita la puesta a punto del programa. En cambio la ejecución resulta más lenta ya que acarrea una traducción simultánea. Observación importante: Un programa en Java puede ser una aplicación o un applet. En este curso aprenderá principalmente a escribir aplicaciones Java. Después aplicará lo aprendido para escribir algunos applets. Dentro de las aplicaciones están las aplicaciones con y sin Swing, en este curso principalmente aprenderá aplicaciones mixtas, es decir con y sin Swing. La librería Swing es una librería con interfaces gráficas muy novedosas. Convengamos sin embargo que una aplicación puede tener una forma más sofisticada (al menos sintácticamente), tal como se muestra a continuación, pudiendo tener otros componentes, tales como extend, implement, abstract y otras que luego veremos package package_nombre; import class_nombre; import package_nombre.*; . . . public class ClassNombre { campo-declaracion 1; campo-declaracion 2; . . . metodos-definicion 1; metodos-definicion 2; . . . public static void main(String [] args) { declaracion 1; declaracion 2; . . . ejecucion-declaracion 1; ejecucion-declaracion 2; . . . } }

En general, si quisiéramos ya incorporar elementos de la Programación Orientada a Objetos podríamos haber escrito en forma más general, import java.lang.*; /* Primer programa como una aplicación en POO*/ public class PrimerProgramm extends Object { // Comienzo clásico de los Programas en Java public static void main(String args[]) { // salida estandar Ingeniería en Computación, Universidad de La Seren

34

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

System.out.println( "Nuestro primer programa Java, pero sofisticado."); } }

Notar que la expresión import java.lang.*; siempre existe por defecto, de manera que se puede omitir, además de extends Object dado que toda clase no se crea por si solo, sino que proviene de una clase madre o padre (super clase) en este caso es Object. Una visión de la plataforma JDK La plataforma JDK pone a disposición una serie de comandos y herramientas de utilidad entre las cuales se encuentra:  Java-Compilador: javac, generando Byte-Code Comando: javac ejemplo.java Ejemplo: javac Hola_Alumno.java genera el archivo Hola_Alumno.class y digaHola.class.  Java-Interprete: java, llamando los Bytecode Comando: java ejemplo Importante: La extensión .class no debe incorporarse! Ejemplo: java Hola_Alumno lleva a cabo la aplicación.  Applet-Viewer: appletviewer, sirve para testear los Java-Applets sin Web-Browser Comando: appletviewer ejemplo.html Nota: El Applet debe ser referenciado en una página-HTML. Ejemplo (absolutamente AppletMinimal (Hola_AlumnoApplet.java): appletviewer Hola_AlumnoApplet.html.  Generador de Documentos estándar: javadoc, genera documentación en la forma de HTML-Documentos del código fuente Java y contiene comentarios formales. Comando: javadoc ejemplo.java Ejemplo: javadoc -private -version -author -windowtitle "Ejemplo de un JavaDoc" Hola_Alumno.java  Textmode-Debugger: jdb, Debugger orientado al texto. Comando: jdb ejemplo  Desamblador: javap, recuperar códigos fuentes Java desde Bytecode Comando: javap ejemplo. La devolución del compilado Hola_Alumno.class con javap -c Hola_Alumno se vé, así: Compiled from Hola_Alumnos.java public class Hola_Alumnos extends java.lang.Object { public Hola_Alumnos(); public static void main(java.lang.String[]); } Ingeniería en Computación, Universidad de La Seren

35

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

Method Hola_Alumnos() 0 aload_0 1 invokespecial #1 4 return Method void main(java.lang.String[]) 0 getstatic #2 3 ldc #3 5 invokevirtual #4 8 return

Nota: Si Ud. observa NO se recupera el código fuente original, esto es por razones de protección comercial. Sin embargo, existe un Java-Interpete disponible, llamado JavaRuntime Environment (abrev. JRE). Instalación de Java Como Ud. podrá haber notado, para escribir programas se necesita un entorno de desarrollo Java. Sun MicroSystems, propietario de Java, proporciona una forma gratuita, llamada Java Development Kit(JDK) que se puede obtener en la dirección Web, http://www.sun.com

Ingeniería en Computación, Universidad de La Seren

36

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

Para instalar la versión del CD Rom en una plataforma Windows, hay que ejecutar el archivo j2sdk1_4_0-win.exe. De manera predeterminada el paquete será instalado en jdk1.4, pudiéndose instalar en cualquier otra carpeta. A continuación podrá instalar la documentación en jdk1.4\docs que se proporciona en el archivo j2sdk1_3_0-doc.zip. La carpeta jre es el entorno de ejecución de Java utilizado por el SDK. Es similar al intérprete de Java (java), pero destinado a usuarios finales que no requieran todas las opciones de desarrollo proporcionadas con la utilidad java. Incluye la máquina virtual, la biblioteca de clases, y otros archivos que soportan la ejecución de programas escritos en Java. La carpeta lib contiene bibliotecas de clases adicionales y archivos de soporte requeridos por las herramientas de desarrollo. La carpeta demo contiene ejemplos. Por ejemplo Java2Demo a través de un browser, en este caso a través de Netscape.

La carpeta include contiene los archivos de cabecera que dan soporte para añadir a un programa Java código nativo (código escrito en un lenguaje distinto de Java, por ejemplo Ada o C++). La carpeta include-old contiene los archivos de cabecera que dan soporte para añadir a un programa Java código nativo utilizando interfaces antiguas. Ingeniería en Computación, Universidad de La Seren

37

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

Ahora, que ya tiene todos los archivos y carpetas de la distribución instalados, sólo le falta un editor de código fuente Java. Es suficiente con un editor de texto sin formato; por ejemplo el bloc de notas de Windows. No obstante, todo el trabajo de edición, compilación, ejecución y depuración, se hará mucho más fácil si se utiliza un entorno de desarrollo con interfaz gráfica de usuario que integre las herramientas mencionadas, en lugar de tener que utilizar las interfaz de línea de órdenes del JDK, como veremos a continuación. Algunos entornos de desarrollo integrados para Java son: Forte de Sun, Visual Café de Symantec, JBuilder de Borland, Kawa de Tek- Tools, Visual Age Windows de IBM, pcGRASP de Auburm University, Visual J++ de Microsoft, JPadPro, BlueJ, Eclipse, y otros. La mayoría de ellos se ajustan a las necesidades del curso. Tomar la precaución de que algunos IDE‟s para que funcionen requieren ciertas versiones de Java, infórmese. 

JDK 5.0 ( java.sun.com/j2se/1.5.0/download.jsp).



JBuilder 2005 Foundation (www.borland.com/products/downloads/download_jbuilder.html).



NetBeans 5.5 ( www.netbeans.org).



Eclipse 3.1 ( www.eclipse.org).



TextPad ( www.textpad.com).



JCreator LE ( www.jcreator.com).



JEdit ( www.jedit.org).



JGrasp ( www.bluej.org).



DrJava ( drjava.sourceforge.net).



WinZip ( www.winzip.com).



MySQL ( www.mysql.com).



MySQL JDBC Driver ( www.cs.armstrong.edu/liang/intro6e/book/mysqljdbc.jar).



Tomcat ( www.apache.org).

Verificar que el sistema operativo haya asumido los cambios, producto de la instalación de jdk1.4. Para tal efecto, utilizando líneas de comando MSDOS habrá que añadir a la variable de entorno path la ruta de la carpeta donde se encuentra esta utilidad, como por ejemplo:

Ingeniería en Computación, Universidad de La Seren

38

Dr. Eric Jeltsch F.

Capítulo 2: Fundamentos

A continuación se muestran algunas demos que trae la distribución, las que Ud. puede ejecutar sin dificultad. Por ejemplo,  

C:\jdk1.3.1\demo\sound\JavaSound.jar C:\jdk1.3.1\demo\jfc\Java2D\Java2Demo.jar

Ingeniería en Computación, Universidad de La Seren

39

Dr. Eric Jeltsch F.

Ingeniería en Computación, Universidad de La Seren

Capítulo 2: Fundamentos

40

Dr. Eric Jeltsch F.

Ingeniería en Computación, Universidad de La Seren

Capítulo 2: Fundamentos

41

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

C A P I T U L O III Elementos del Lenguaje En esta lección veremos los elementos que aporta Java (caracteres, tipos de datos, operadores, y otros) para escribir un programa. Considere esta lección como soporte para el resto de las lecciones. Tipos de Datos y Strings Integers Hemos visto que no todos los valores tratados por programas Java son objetos. Los tipos de valores simples, tales como integers y floating-point son tratados en forma diferente y son llamados tipos de datos primitivos. Empezaremos con el uso de los enteros (integers.) Suponga que Ud. visitó Miami, y al regresar le quedan 8 pennies, ningún nickels, 5 dimes y 6 quarters. Cuanto tiene en total? Para trabajar la respuesta sepa que un penny es una moneda de 1 cent., un nickel son 5 cents, un dime son 10 cents, y un quarter es un cuarto de dólar o 25 cents. A través del siguiente programa no le será difícil saber que Ud. tiene 208 cents. El siguiente programa ilustra varios puntos de interés respecto al trabajo con enteros. Ejemplo 1 public class Cambio1 { /* Calcular cuantas monedas Ud. tiene (en cents) Sabiendo que tiene 6 quarters, 5 dimes, ningún nickels, y 8 pennies(o centavos en USA). */ public static void main(String[] args) { System.out.print("Ud. tiene "); System.out.print(6*25 + 5*10 + 0*5 + 8); System.out.println(" cents."); }

//declaración1 //declaración2 //declaración3

}

En ejemplo1, el método main contiene tres declaraciones. Cuando lo ejecuta, las tres declaraciones generan tres partes de línea simple sobre la pantalla. Note que las primeras 2 usan print en vez de println. Permitiendo que el valor 208 aparezca inmediatamente después de la palabra Ud. tiene, sobre la misma línea, y cents aparece después. Ud.tiene

208

cents

Generado por declaración1

declaración2

declaración3

Ingeniería en Computación, Universidad de La Seren

42

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

Cuando Java obedece la declaración2, calculara el valor de la expresión aritmética (El símbolo  denota multiplicación.) 6*25 + 5*10 + 0*5 + 8 desplegando el resultado, 208. Algunos Operadores En Java los siguientes operadores pueden ser usados con expresiones aritméticas. +   / %

adición substracción multiplicación división módulo

En Java (y muchos otros lenguajes de programación) números son ya sea integers o floatingpoint. Estos 2 tipos son almacenados en memoria en diferentes sentidos. Si el valor es, por ejemplo 4, se trata de un integer. Por otro lado si es 4.0, será tratado como floating-point. Todos los valores del Ejemplo1 son integers. En la medida que pueda siempre use integers, pues serán tratados más rápido al requerir menos memoria, y no existe peligro de redondeo. El operador, /, tiene 2 formas. Si es usado con 2 integers entonces es integer division (división entera). Por ejemplo, 11 / 4 = 2, (11) / 4 = 2. Si es usado con dos valores floating-point , o un integer y un valor floating-point, denota división normal. Por ejemplo, 10.5 / 2 = 5.25. El módulo o resto es solamente usado con dos integers. Por ejemplo, 11%4 = 3 y (11)%4 = 3. Si evalúa m/n o m%n donde n es cero, le envía un error. En los procesos de evaluación, Java asume que los operadores , / y % tienen más alta prioridad que la + y la . Por ejemplo, 3+45 es lo mismo que 3+(45), pero no (3+4)5. Cuando evalúa expresiones con varios operadores + y  en una fila, o varios operadores , / y % en una fila, el criterio es de izq. a der. Por ejemplo, 345 es lo mismo que (34)5, no 3(45). Similarmente 3/4/5 es lo mismo que (3/4)/5, no 3/(4/5) (el que produce un error). Variables Ejemplo2 public class Cambio2 { /* Idem Ejemplo1. */ public static void main(String[] args) { int total = 6*25 + 5*10 + 0*5 + 8; System.out.print("Ud. tiene "); System.out.print(total/100); System.out.print(" dólares con "); System.out.print(total%100); System.out.println(" cents."); } }

Ingeniería en Computación, Universidad de La Seren

43

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

El Ejemplo2 es otra versión del programa Ejemplo1, esta vez haciendo uso de variables. La declaración

int total = 6*25 + 5*10 + 0*5 + 8;

nos dice: crea una variable total que denota la expresión 625 + 510 + 05 + 8 ( = 208). La palabra int muestra que el valor de total es un valor integers. Llamado declaración de variable. La declaración System.out.print(total/100);

dice: la salida es el cuociente entre total que es dividido por 100 (división entera). Es decir 208/100 (= 2) es la salida. La declaración System.out.print(total%100);

dice: la salida es el resto de la división de total dividido por 100. Es decir 208%100 (= 8). Esto es lo que se despliega en pantalla. Ud. tiene

2

dólares con 8

cents

Ejemplo 3 public class Cambio3 { public { int int int int

static void main(String[] args) quarters = 6; dimes = 5; nickels = 0; cents = 8;

int total = quarters*25 + dimes*10 + nickels*5 + cents; System.out.print("Ud. tiene "); System.out.print(total/100); System.out.print(" dólares con "); System.out.print(total%100); System.out.println(" cents."); } }

Si al ejemplo 2 se le incorpora la declaración de variables, se genera el Ejemplo 3. Es importante mencionar que en Java, cuando una variable es creada tiene un área de memoria para almacenar sus valores. La memoria depende del tipo de dato que se le asigno a la variable en la declaración. Por ejemplo, si la declaración dice que es de tipo int, como es el caso de la variable total, dejara 32 bits de memoria. El valor de una variable int esta en el rango 2147483648 a 2147483647. Si maneja enteros más grande reemplace int por long, a lo que la variable le dejará 64 bits de memoria. Ingeniería en Computación, Universidad de La Seren

44

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

Asignaciones Toda variable tiene un nombre y una porción de memoria, según el tipo de dato declarado. Decimos que el valor en la porción de memoria es el valor asignado a la variable. En el siguiente ejemplo el valor de la variable peso es cambiada una vez. Ejemplo 4 public class Peso1 {

/* Calcula las libras a kilos dado el peso almacenado en libras. */ public static void main(String[] args) {

int stones = 10; int libras = 8; libras = 14*stones + libras; double kilos = libras * 0.4536; System.out.print("Ud. pesa "); System.out.print(kilos); System.out.println(" kilos.");

} }

Este programa parte creando 2 variables llamadas stones y libras . (1 stone = 14 libras.) y declara libras = 14*stones + libras;

esto dice: calcula el valor de la expresión 14*stones + libras, y almacena el resultado en la variable libras. En otras palabras, reemplaza el valor original almacenado en libras (= 8) por la persona con peso total en libras (= 148). La declaración

double kilos = libras * 0.4536;

es nuestro primer ejemplo de cómo usar el valor floating-point. Y dice: crea una variable llamada kilos de tipo double, y le asigna el valor libras * 0.4536 . Una variable de tipo double posee 64 bits de memoria. El producto de un entero y un floating-point es calculado en floating-point. En este caso la respuesta será 67.1328. Una vez que el peso de la persona ha sido calculado, las últimas tres declaraciones entregan la respuesta. Ud. pesa 67.1328 kilos.

La declaración

libras = 14*stones + libras;

es una declaración de variable de tipo int. Esto significa que cuando Java obedece la declaración de asignación la realiza en 2 etapas: primero evalúa la expresión a la derecha de „=‟, y almacena el resultado en la variable a la izquierda de „=‟. De esta manera cuando agregamos 15stones y el valor original en libras, obtendremos la respuesta en la variable Ingeniería en Computación, Universidad de La Seren

45

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

libras, libras.

sobreescribiendo en el antiguo valor. En efecto, agregamos 14stones al valor de Si a menudo necesita hacer este tipo de declaraciones, hágalo como en C. En tal caso podrá escribir. libras += 14stones;

que dice: adicione 14stones a libras. Similarmente puede usar = para cuando quiera restar o substraer un valor desde una variable, y podemos usar = cuando queramos multiplicar una variable por el valor, y así sucesivamente. Uno de los ejemplos más comúnes en este tipo de declaraciones es para cuando queremos adicionar 1 al valor de la variable. En tal caso podemos escribir, por ejemplo, x += 1;

para sumar 1 al valor de x. Sin embargo, es más común una declaración del tipo x++;

Similarmente para restar 1 desde x, podemos escribir x--. Ud. podrá cambiar el valor almacenado en la variable, pero nunca podrá cambiar el tipo de valor. Por ejemplo, dada la declaración de la variable int libras en el último ejemplo, cualquier nuevo valor asignado a él deberá ser un entero, y siempre será almacenado en 32 bits de memoria. El siguiente diagrama describe las diferentes formas de declaración.

declaración (con un valor inicial) Tipo Nombre = Expresion ;

Por ejemplo, Tipo puede ser int, Nombre puede ser quarters, y Expresion ser 6. Esta sería la declaración int quarters = 6; Punto Flotante. El nombre punto flotante “floating-point” proviene en el sentido que estos números son representados en la memoria del computador. La notación es similar a la notación científica (es decir, 1.0751024), pero usando base 2 en vez de base 10. En Java, el tipo de dato double es el usado más comúnmente para valores punto flotante. 64 bits son usados para valores double. Siendo el rango de los valores: aproximadamente 1.810308, equivalente a 15 dígitos significativos. El nombre double es para „double precision floating-point’. Java tiene un segundo tipo de dato para tratar números floatingpoint, llamados float. Este tipo de dato usa solamente 32 bits para los valores, siendo más económico en el uso de memoria, pero tiene la mitad de la precisión de double. Ingeniería en Computación, Universidad de La Seren

46

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

Los números floating-point pueden ser escrito con punto decimal, es decir, 14.56 o 14.0. Puede también ser escrito con exponente, es decir, 14.56E-12, que es equivalente a 14.561012. Como cualquier tipo de dato, podemos declarar variables de tipo double. Por ejemplo, double radio = 1.67;

que creará una variable llamada radio, considerando 64-bit en memoria que contiene el valor inicial 1.67. Funciones Estándares Java proporciona métodos que calculan el rango de las funciones matemáticas usando valores double. Aquí hay algunos ejemplos, ellos son métodos static (es decir, métodos que NO pertenecen a un objeto) en la librería Math de Java. Math.sin(x) Math.cos(x) Math.tan(x) Math.exp(x) Math.log(x) Math.abs(x) Math.floor(x) Math.ceil(x)

seno de x coseno de x tangente de x ex log natural de x valor absoluto de x entero más grande que sea  x entero más pequeño que sea  x

En cada caso el parámetro x es de tipo double y el resultado es de tipo double. Notar la perdida de precisión que se obtiene con float r; r= (float)Math.sqrt(10);

pues el resultado se redondea perdiendo precisión ya que sqrt() devuelve un valor de tipo doble. Algunas otras observaciones, son las siguientes, int m = 3; int n = 4; double x = mn;

cuando Java ejecuta la tercera declaración evalua mn usando aritmética entera para dar 32-bit al valor entero 12. Entonces convertirá el valor 12 a 64-bit floating-point, que será almacenado en x. Si reemplazamos, la tercera declaración por, double x = m/n;

la respuesta es que x será seteado a 0. La razón es que en aritmética entera usará la expresión m/n, y el operador será división entera. Así el valor es cero.

Ingeniería en Computación, Universidad de La Seren

47

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

Suponga que queremos usar una división normal en floating-point para trabajar sobre x Debemos entonces tratar el valor de m y n como valor floating-point. Pudiendo escribir, double x = ((double) m) / n;

El término (double) es llamado cast. Podemos usar casts para transformar un valor de un tipo cualquiera que sea en un valor equivalente de otro tipo. La parte entera de un número floating-point. Por ejemplo, el número floating-point 4.7 se convierte en el entero 4. El camino para hacer esto en Java es usar el cast int. Supongamos lo siguiente, double x = 4.7; int i = (int) x;

la segunda declaración convertirá el valor de x al entero 4, y lo almacenará en i. Si x ha sido seteado a 4.7, i tomará el valor 4. Redondear el número. Por ejemplo, el techo de 4.7 es 5. Supongamos lo siguiente, procurando que el valor no sea negativo. int i = (int) (x + 0.5);

Por ejemplo, si x es igual a 4.7, el valor de x + 0.5 será 5.2, y el valor de(int)(x + 0.5) será 5, el cual es el techo de 4.7. Sin embargo, si x es 4.7, se obtiene que el valor de x + 0.5 será 4.2, y el valor de (int)(x + 0.5) será 4, el que no es el techo de 4.7. Ejemplo 5. // Demo para practicar con los tipos de datos y operadores class BasicaMate { public static void main(String args[]) { // aritmetica usando integers System.out.println("Aritmética"); /* double x =4.7; int i = (int) (x + 0.5); System.out.println("x es " + x); System.out.println("i es " + i); */ /* double r; r= Math.sqrt(10); */ float r; r=(float)Math.sqrt(10); int m = 3; int n = 4; double x = m/n; double z = ((double) m) / n; System.out.println("r es " + r); System.out.println("m es " + m); System.out.println("n es " + n); System.out.println("x es " + x); Ingeniería en Computación, Universidad de La Seren

48

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

System.out.println("z es " + z); } }

Clases de I/O Por lo general, cada texto introductorio en el lenguaje Java trae hoy en día sus propias clases, generando que inevitablemente debamos conocer como trabajan las clases, los métodos y la forma de ingresar y retornar datos. Tal como se mencionaba, en la Lección1 Fundamentos),el libro Java How To Program (Deitel & Deitel 3Ed.) posee el paquete com.deitel.jhtp3.*, de la misma manera el libro de Cay S. Horstmann, Core Java 2, Volumen I, (Fundamentals) trae el paquete corejava, y David Flanagan trae el paquete com.davidflanagan.*. Con esto quiero decir que en la práctica siempre nos encontraremos con libros que de una u otra manera tienen enfoques distintos y distintas clases para tratar el ingreso y retorno de datos. Frecuentemente un programa necesita obtener información desde un origen o enviar información a un destino, hasta el momento los datos son estáticos, es decir han sido incorporados al programa a través de asignaciones simples con expresiones aritméticas. Sin embargo en general la comunicación entre el origen de cierta información y el destino, se realiza mediante un flujo de información (llamado, stream en inglés), que es un objeto que hace de intermediario entre el programa, y el origen o el destino de la información. Luego, para que un programa pueda obtener información desde un origen tiene que abrir un flujo y leer la información, análogamente para escribir la información. De allí que necesitemos incorporar datos en forma dinámica a través del teclado. Todas las clases relacionadas con flujos en la distribución estándar de Java están en el paquete java.io, de manera que en rigor debería importar este paquete en el encabezado mediante la declaración import java.io.*; en el encabezado del programa. Sin embargo, Java lo importa por defecto, de manera que no se preocupe de hacerlo. Como ya habíamos mencionado, existen normalmente tres flujos de datos de I/O conectados a su programa: System.in--- el flujo de entrada. System.out--- el flujo para los resultados normales. System.err--- el flujo para los mensajes de error.

Normalmente System.in se conecta al teclado y los datos son carácteres. System.out y System.err se conectan ambos al monitor, y los datos son carácter. Los datos que un teclado envía a un programa son datos character, incluso cuando los carácteres incluyen los digitos ' 0 ' a ' 9 '.

Si su programa hace aritmética, los caracteres de la entrada se convertirán en uno de los tipos numéricos primitivos. Se calcula (usando aritmética), y luego el resultado se convierte a dato character. La información que un programa envía al monitor son datos character: Ingeniería en Computación, Universidad de La Seren

49

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

(Realmente, los caracteres no se envían directamente al monitor, sino que ellos se convierten primero en una señal de video por la tarjeta gráfica. Esta forma de convertir datos de una forma a otra es muy común). El siguiente programa lee characters desde el teclado en el String llamado enDato. Luego los caracteres almacenados en String son enviados al monitor. Ejemplo 6. import java.io.*; class Eco{ public static void main (String[] args) throws IOException { InputStreamReader inStream = new InputStreamReader( System.in ) ; BufferedReader stdin = new BufferedReader( inStream ); String enDato; System.out.println("Ingrese el dato:"); enDato = stdin.readLine(); System.out.println("Ud. ingreso:" + enDato ); } }

La línea import java.io.*; dice que el paquete java.io será usado y * significa que cualquier clase al interior del paquete sera usada. IOException

es necesario para programas que tienen entrada por teclado (por lo menos por ahora.) para informarle al compilador que main() tiene un funcionamiento de entrada que eventualmente podría fallar. A lo que si el programa que se está ejecutando y un funcionamiento de la entrada falla, el sistema le informará del fracaso y el programa se detendrá. En otras lecciones donde tratemos (Exceptions) veremos con más detalle esta y otras situaciones. Examinemos las siguientes declaraciones, que son básicas para el I/O de datos en Java. (1) InputStreamReader inStream = new InputStreamReader (System.in); (2) BufferedReader stdin= new BufferedReader (inStream);

La (1) construye un objeto de InputStreamReader y le da el nombre inStream. La (2) construye un objeto de BufferedReader llamado stdin que lo conecta al inStream. Pudiendo escribirse en forma resumida como Ingeniería en Computación, Universidad de La Seren

50

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

BufferedReader stdin = new BufferedReader( new InputStreamReader( System.in ) ); La variable inStream. es usada para conectar el InputStreamReader a la BufferedReader.

Observar que si Ud. quisiera que el usuario ingresara datos numericos, su programa debería convertir los caracteres a tipo de dato numérico. Para ello no olvidar que los caracteres son primero leídos en un objeto String para luego convertirlo a dato numérico. Para tal efecto se usa la declaración enDato = stdin.readLine(); num = Integer.parseInt( enDato );// convertir a int

Aquí se muestra una nueva versión del programa Peso1.java , usando BufferReader. Ejemplo 7. import java.io.*; public class PesoBuffer { /* Calcula las libras a kilos dado el peso almacenado en libras. */ public static void main(String[] args) throws IOException { BufferedReader stdin = new BufferedReader ( new InputStreamReader( System.in ) ); String stones, libras; int num, num1; double kilos; System.out.println("Digame su peso."); System.out.print("Cuantos stones: "); stones = stdin.readLine(); num = Integer.parseInt( stones ); System.out.print("Cuantas libras: "); libras = stdin.readLine(); num1 = Integer.parseInt(libras); num1 = 14*num + num1; kilos = num1 * 0.4536; System.out.print("Ud. pesa "); System.out.print(kilos); System.out.println(" kilos."); }//end main }//end PesoBuffer

Ingeniería en Computación, Universidad de La Seren

51

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

Aquí se muestra un ejemplo de lo que aparece en pantalla. (Usando input en boldface.) Digame su peso. Cuantos stones: 8 Cuantas libras: 5 Ud. pesa 53.0712 kilos.

ConsoleReader ConsoleReader es otra clase usada para leer datos de entrada. Horstmann en su libro Core Java, proporciona un paquete corejava para, entre otras cosas, leer la entrada de datos por teclado. La clase es llamada ConsoleReader, que está habilitada en un archivo de nombre ConsoleReader.java. Para usarla basta insertar la siguiente declaración ConsoleReader in = new ConsoleReader(System.in);

en su programa, y no olvidar de guardar su programa junto con ConsoleReader en el mismo directorio, o bien guardar la extensión ConsoleReader.class en la misma carpeta de trabajo, así podrá acceder el objeto System.in, el que está conectado al teclado. in.readInt() in.readDouble() in.readLine()

// devuelve un valor int. // devuelve un valor double. // devuelve un string, que consiste de todos los caracteres ingresados por consola por el usuario hasta el fin de línea.

Aquí se muestra una nueva versión del programa Peso1.java , usando ConsoleReader. Ejemplo 8 public class PesoConsole {

/* Calcula las libras a kilos dado el peso almacenado en libras. */ public static void main(String[] args) {

ConsoleReader in = new ConsoleReader(System.in);

System.out.println("Digame su peso."); System.out.print("Cuantos stones: "); int stones = in.readInt(); System.out.print("Cuantas libras: "); int libras = in.readInt(); libras = 14*stones + libras; double kilos = libras * 0.4536; System.out.print("Ud. pesa "); System.out.print(kilos); System.out.println(" kilos."); }//end main } //end PesoConsole

Ingeniería en Computación, Universidad de La Seren

52

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

Aquí se muestra un ejemplo de lo que aparece en pantalla. (Usando input en boldface.) Digame su peso. Cuantos stones: 8 Cuantas libras: 5 Ud. pesa 53.0712 kilos.

Obs: Ud. verá el siguiente mensaje si no tiene la librería o archivo ConsoleReader C:\Documents and Settings\usuario\Escritorio\POO\lect_Jpoo_06\source2\PesoConsole.java:8: cannot resolve symbol symbol : class ConsoleReader location: class PesoConsole { ConsoleReader in = new ConsoleReader(System.in); ^ C:\Documents and Settings\usuario\Escritorio\POO\lect_Jpoo_06\source2\PesoConsole.java:8: cannot resolve symbol symbol : class ConsoleReader location: class PesoConsole { ConsoleReader in = new ConsoleReader(System.in); ^ 2 errors Herramienta completada con código de salida 1.

Para evitar esto, deberá incluir el archivo ConsoleReader.class en el directorio en donde Ud. está trabajando. hsa.* A continuación, se muestra otro ejemplo de Peso1.java, usando el paquete hsa que lo puede obtener de la dirección Web: http://www.holtsoft.com/java/hsa_pkg_overview.html Ejemplo 9. import hsa.*; public class PesoHsa { /* Calcula las libras a kilos dado el peso almacenado en libras. */ public static void main (String [] args) { int libras, stones; System.out.println("Digame su peso."); System.out.print("Cuantos stones: "); stones = Stdin.readInt(); System.out.print("Cuantas libras: "); libras = Stdin.readInt(); libras = 14*stones + libras; double kilos = libras * 0.4536; System.out.print("Ud. pesa "); System.out.print(kilos); System.out.println(" kilos."); //System.out.println("The number: " + aNum); } //end main } //end PesoHsa Ingeniería en Computación, Universidad de La Seren

53

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

Swing Y finalmente mediante el uso de la librería Swing. Observar que el encabezado invoca a la dirección javax.swing.JOptionPane; Ejemplo 10. import javax.swing.JOptionPane; public class PesoSwing { /* Calcula las libras a kilos dado el peso almacenado en libras. */ public static void main( String args[] ) { int stones, libras; String entrada; // prompt para input y leer la entrada entrada = JOptionPane.showInputDialog("Digame su peso. Cuantos stones: " );

// convertir la entrada de String a integer stones = Integer.parseInt( entrada ); entrada = JOptionPane.showInputDialog("Cuantas libras: " );

// convertir la entrada de String a integer libras = Integer.parseInt( entrada ); libras = 14*stones + libras; double kilos = libras * 0.4536; // display el promedio de los datos JOptionPane.showMessageDialog( null, "Ud. pesa " + kilos + " kilos ", "Resultado", JOptionPane.INFORMATION_MESSAGE );

Ingeniería en Computación, Universidad de La Seren

54

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

System.exit( 0 );

// termina el programa

} }

Es así como podríamos continuar haciendo funcionar nuestros programas soportados por diversas librerías de clases. Sin embargo, lo que deseo transmitir es que aprenda a tener la capacidad de incursionar en otros tipos de paquetes y clases para ver el que le convenga o sino buscar nuevas alternativas o bien generar sus propias clases. Modelemos desde un punto de vista más abstracto una arquitectura para la aplicación que transforma grados Celsius a Fahrenheit. Por ejemplo,

Ejemplo 11. CelsiusToFarehheit2 main JOptionPane showInputDialog

Integer intValue

System.out main

DecimalFormat format

import java.text.*; import javax.swing.*; /** CelsiusToFahrenheit2 convierte Celsius a Fahrenheit. * input: los grados Celsius, se lee un integer de dialog * output: los grados Fahrenheit, un double */ public class CelsiusToFahrenheit2{ public static void main(String[] args) { String input = JOptionPane.showInputDialog("Ingresar entero, Cº T.:"); int c = new Integer(input).intValue(); // convierte input en un int double f = ((9.0 / 5.0) * c) + 32; DecimalFormat formato = new DecimalFormat("0.0"); System.out.println("para Cº Celsius " + c + ","); System.out.println("grados Fº Fahrenheit = " + formato.format(f)); } }

Ingeniería en Computación, Universidad de La Seren

55

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

cuyo resultado es 73.4 Fº, pero en MS-DOS. Sin embargo a veces es necesario ingresar los datos por teclado y con varios parámetros a la vez. Esto último lo veremos en el próximo capítulo. Ahora, nos falta aprender el ingreso de datos a través de archivos, que sean leídos por el programa, tratados o manipulados por él, para luego ir a depositarlos en otro archivo de salida, por ejemplo. Esto lo veremos más adelante, en las siguientes secciones. El propósito del siguiente ejemplo es mostrar entrada y salida de datos usando la consola y los archivos de la clase hsa. El paquete hsa posee muchas otras clases que le pueden ser de utilidad. Ud. podrá comprobar tras la ejecución del programa ArchivoHsaDemo.java que en el archivo salida.txt en su carpeta de trabajo están los datos 34, 56, 78, 90, 12. Además intente ingresar un número NO entero y verá otra de las gracias del paquete hsa, y digo “gracia” porque el código no posee declaraciones try-catch (atrapa excepciones). Ejemplo 12. import hsa.*; public class ArchivoHsaDemo { public static void main (String [] args) { int [] numsArray = {34, 56, 78, 90, 12}; int i, aNum; String entraString, saleString; //Screen Input en la Consola System.out.print("Ingrese un número entero: "); aNum = Stdin.readInt(); // Screen Output para un número System.out.println("El número es: " + aNum); //Archivo Texto de Output TextOutputFile saleFile = new TextOutputFile ("salida.txt"); for (i = 0 ; i < numsArray.length ; i++) saleFile.println (numsArray [i]); saleFile.close (); //Archivo Texto de Entrada int numNums = 0; int[] leerNums; TextInputFile enFile = new TextInputFile ("salida.txt"); Ingeniería en Computación, Universidad de La Seren

56

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

while (!enFile.eof()) { aNum = enFile.readInt(); numNums++; } // end while enFile.close(); leerNums = new int [numNums]; enFile = new TextInputFile ("salida.txt"); for (i = 0; i < numNums; i++) leerNums[i] = enFile.readInt(); enFile.close(); // Chequear los números que han sido leídos. saleString = "Los números son: "; for (i = 0 ; i < numNums ; i++) saleString = saleString + leerNums [i] + ", "; System.out.println(saleString); } //end main method } //end ArchivoHsaDemo

Strings. Esta sección contiene información sobre uno de los tipos de datos más comunes, strings. Un literal string es escrito entre comillas. Por ejemplo, el perro. Si el literal es vacío se escribe  . Un string puede contener control de caracteres, esta es una lista de combinaciones que se pueden hacer. \n \t \b \r \f \\ \ \

Por ejemplo,

newline tab backspace return line feed \ character  caracter  caracter

System.out.print(El\nfin);

Escribirá „El‟ en una línea y en la otra línea verá „fin‟. Si desea almacenar un string basta usar una variable de tipo String. Por ejemplo, String animal = perro;

La concatenación es denotada por „+‟. Por ejemplo, si la variable animal ha sido asignada a perro, entonces la expresión El  + animal +  corre. denota el string El perro corre. Expresiones usuales en programas son por ejemplo, la declaración System.out.println(El  + animal +  corre.);

Ingeniería en Computación, Universidad de La Seren

57

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

que desplegara el mensaje El perro corre. sobre la pantalla. Por otra parte El  + animal +  corre + cuanTas +  veces, denota el string El perro corre 10 veces.

Si recuerda estas declaraciones System.out.print("Ud. tiene "); System.out.print(total/100); System.out.print(" dólares con "); System.out.print(total%100); System.out.println(" cents.");

Las cinco declaraciones han sido combinadas en una sola, System.out.println ( Ud. tiene  + (total/100) +  dolares con  + (total%100) +  cents. );

El siguiente programa usa los métodos usuario.readLine() para leer el nombre del usuario y usuario.readInt() para leer la edad. Ejemplo 13 public class Chatear { {

/* Chateando. */ public static void main(String[] args)

ConsoleReader usuario =new ConsoleReader(System.in); System.out.println ("Hola. Cómo te llamas?"); String nombre = usuario.readLine(); System.out.println ("Que edad tienes " + nombre + "?"); int edad = usuario.readInt(); System.out.print(edad + "no esta mal la edad, "); System.out.println ("pues yo tengo " + (edad+1) + " que es mejor."); System.out.println ("Hasta la vista " + nombre + "."); } }

En pantalla podrá ver, Hola. Como te llamas? Alicia Lobos Que edad tienes Alicia Lobos? 20 20 no esta mal, pues yo tengo 71 que es mejor. Hasta la vista Alicia Lobos.

Ingeniería en Computación, Universidad de La Seren

58

Dr. Eric Jeltsch F.

Capítulo 3: Elementos del Lenguaje

Algunas expresiones útiles st.substring(m,n), tal como animal.substring(5,8) genera el string nte, tal como se describe. e

l

0

1

e 2

f 3

n

a 4

5

6

t

e

7

8

Java tiene un tipo de dato llamado String que difiere de los 8 tipos primitivos, en lo fundamental porque un valor del tipo string es un objeto. Un string no es justamente un valor de dato, también tiene "métodos". (Un método es un subprograma que es parte de un objeto.) por ejemplo, si str es una variable de tipo String, Ud. puede llamar al método str.length(), que es una función que devuelve el número de carácteres en el string. Hay mucho más que usted puede hacer con string. Una cosa que usted no puede hacer con string es usar los operadores , = 0) && (minuto = 0) && (minuto (64 >= 0) && (minuto true && (minuto true && (64 true && false => false

TABLA 1: Operadores Lógico Operador

Semantica

E1 && E2

conjunción (``and''): true && true => true true && false => false false && E2 => false

E1 || E2

disjunción (``or''): false || false => false false || true => true true || E2 => true

!E

negación(``not''): !true => false !false => true

La semántica debe respetarse, por ejemplo: (2 != 1) || (x == 3.14) => true || (x == 3.14) => true

esta disjunción, ||, resulta ser true, por lo tanto no existe necesidad de calcular el 2º argumento, resultando la expresión, true.

Ingeniería en Computación, Universidad de La Seren

64

Dr. Eric Jeltsch F.

Capítulo 4: Estructuras de Control

Ejemplo 2 Otro ejemplo interesante es considerar el método: deposit(int monto): boolean, que trata de especificar lo siguiente.. 1. Si monto es no-negativo, entonces adiciona monto a la cuenta balance. 2. de otra manera, use un error de mensaje e ignore el depósito. 3. return el resultado. Vea la salida y siga practicando, dándose otras situaciones. import javax.swing.*; /** BankCuenta administra una cuenta simple */ public class BankCuenta{ private int balance;

// balance >= 0

siempre!

/** Constructor BankCuenta inicializa la cuenta * @param inicial_m – cuenta balance,nonegativo. */ public BankCuenta(int inicial_m) { if ( inicial_m >= 0 ) { balance = inicial_m; } else { balance = 0; } } /** deposita adiciona dinero a la cuenta. * @param monto – el monto a ser agregado, un int nonegativo * @return true, si el deposito sucedio; false, en otro caso */ public boolean deposit(int monto) { boolean result = false; if ( monto >= 0 ) { balance = balance + monto; result = true; } else { JOptionPane.showMessageDialog(null, "BankCuenta error: mal el monto del deposito---ignorado"); } return result; } /* sacarMonto, elimina dinero desde la cuenta, si es posible. * @param monto – el monto de dinero a ser eliminado, un int nonegativo * @return true, si la eliminación ocurrió; false, en otro caso */ public boolean sacarMonto(int monto) { boolean result = false; if ( monto < 0 ) { JOptionPane.showMessageDialog(null, "BankCuenta error: monto malo---ignorado"); } else if ( monto > balance ) { JOptionPane.showMessageDialog(null, "BankCuenta error: monto a sacar excede balance"); } else { balance = balance - monto; result = true; } return result; } Ingeniería en Computación, Universidad de La Seren

65

Dr. Eric Jeltsch F.

Capítulo 4: Estructuras de Control

/* getBalance reporta lo ocurrido en balance * @return balance */ public int getBalance() { return balance; } // Un test de la propuesta: public static void main(String[] args){ BankCuenta tester = new BankCuenta(0); // test objeto // tratar con el método getBalance: System.out.println("Inicial balance = " + tester.getBalance()); // tratar con deposito: boolean test1 = tester.deposit(5050); // depositamos 5050 pesos System.out.println("Deposito es " + test1 + ": " + tester.getBalance()); // tratar con sacarMonto: boolean test2 = tester.sacarMonto(3033); System.out.println("el monto a sacar es " + test2 + ": " + tester.getBalance()); // tratar una “mistake”: boolean test3 = tester.sacarMonto(6000); System.out.println("el monto a sacar es" + test3 + ": " + tester.getBalance()); } }

Ejemplo 3 public class Multiplica1 {

/* Un usuario busca saber cuanto es 72 veces 84, y chequear su respuesta. */ public static void main(String[] args)

{ ConsoleReader usuario =new ConsoleReader(System.in); System.out.println("Cuanto es 72 veces 84?"); int resp = usuario.readInt(); if (resp == 6048) System.out.println("Exito!"); else System.out.println("Error!"); } }

Aquí se muestra la salida. Cuanto es 72 veces 84? 6048 Exito!

Y aquí un ejemplo para el caso de no estar en lo correcto. Cuanto es 72 veces 84? 5704 Error! Ingeniería en Computación, Universidad de La Seren

66

Dr. Eric Jeltsch F.

Capítulo 4: Estructuras de Control

La forma general de la estructura if es,

El esquema siguiente corresponde al programa anterior usando diagramas de flujo

Ingeniería en Computación, Universidad de La Seren

67

Dr. Eric Jeltsch F.

Capítulo 4: Estructuras de Control

En el siguiente ejemplo, se muestra otra alternativa de uso de la estructura if, Ejemplo 4 public class Multiplica2 { /* Un usuario busca saber cuanto es 72 veces 84, y chequear que la respuesta es 6048. */ public static void main(String[] args) { ConsoleReader usuario =new ConsoleReader(System.in); System.out.println("Cuanto es 72 veces 84?"); int resp = usuario.readInt(); if (resp == 6048) System.out.println("Exito!"); else { System.out.println ("Error. Trate otra vez."); resp = usuario.readInt(); if (resp == 6048) System.out.println ("Exito."); else System.out.println ("No. La respuesta es 6048"); } } }

Ingeniería en Computación, Universidad de La Seren

68

Dr. Eric Jeltsch F.

Capítulo 4: Estructuras de Control

Existe una forma corta de usar if. Por ejemplo, if (a < b) then System.out.println(El número más pequeño es + a);

Que dice: Si a es menor que b despliega un mensaje, de otra manera NO hace nada.

Esta

if (a < b) then System.out.println(El número más pequeño es + a); else {} es una forma más general de una rama en if,

if (con una rama) if (EXPRESION-Booleana) Declaración

Otra forma un tanto más general, s = a; if (b < s) s = b; if (c < s) s = c; if (d < s) s = d;

Por ejemplo, si a, b, c y d tienen los valores: a = 5,

b = 10,

c = 3,

d = 8.

Las respuestas serán:. 1. 2. 3. 4.

La primera declaración almacena un 5 en s. (Ahora s contiene el 5.) La segunda, no hace nada pues 10 < 5 es false. (Sigue s con 5) La tercera almacena 3 en s, pues 3 < 5 es true. (Ahora s contiene 3.) La cuarta, no hace nada pues 8 < 3 es false. (Sigue s con 3.)

Note que la declaración if siempre contiene el valor más pequeño de los valores testeados, de manera que al final, s contiene el más pequeño de todos los valores. Una forma simple de if con una rama es usar la declaración return. Aquí les muestro un programa que usa el método Math.sqrt para calcular la raíz cuadrada para el usuario.

Ingeniería en Computación, Universidad de La Seren

69

Dr. Eric Jeltsch F.

Capítulo 4: Estructuras de Control

Ejemplo 5 public class RaizCua { /* Busca el usuario calcular la raíz cuadrada de un número, para ello ingresa un valor y la salida es lo que espera. */ public static void main(String[] args) { ConsoleReader in = new ConsoleReader(System.in); System.out.print("Ingrese un número: "); double x = in.readDouble(); if (x < 0) { System.out.println ("Número debe ser >= 0."); return; } System.out.println ("La raíz cuadrada es " + Math.sqrt(x)); } }

Aquí se muestra un ejemplo de la salida. Ingrese un número: 9.2 La raíz cuadrada es 3.03315017762062 Ingrese un número: -3 Número debe ser >=0.

Esta es la forma común de este tipo de estructura, return (con valor de return)

return statement (sin valor de return)

return EXPRESION;

return;

La primera forma es usada al interior de un método que retorna un valor. Que dice: termina obedeciendo este método y retorna el valor dado por la EXPRESION. El segundo es usado al interior de un método que no retorna valor.  Escogiendo entre alternativas A menudo es necesario escoger entre 3 o más alternativas. Esto puede hacerse combinando varios if. Por ejemplo, Si el rango de consumo de agua está entre 70 – 100 costo = A Si el rango de consumo de agua está entre 60 – 69 costo = B Si el rango de consumo de agua está entre 50 – 59 costo = C Si el rango de consumo de agua está entre 40 – 49 costo = D Si el rango de consumo de agua está entre 30 – 39 costo = E Si el rango de consumo de agua está entre 20 – 29 costo = F Si el rango de consumo de agua está entre 10 – 19 costo = G Si el rango de consumo de agua está entre 0 – 9 costo = H. Ingeniería en Computación, Universidad de La Seren

70

Dr. Eric Jeltsch F.

Capítulo 4: Estructuras de Control

En tal caso, basta considerar las declaraciones if (rango >= 70) costo = A; else rango estará entre 0 a 69. if (rango >= 70) costo = A; else if (rango >= 60) costo = B; else rango estará entre 0 a 59.

Eventualmente puede tener if (rango >= 70) costo = "A"; else if (rango >= 60) costo = "B"; else if (rango >= 50) costo = "C"; else if (rango >= 40) costo = "D"; else rango = "F";

Aquí mostramos un programa completo que convierte un rango ingresado por usuario en costos. Ejemplo 6 public class Costos { /* Lee un valor en el rango 0 a 100, y como salida le entrega el costo. */ public static void main(String[] args) { ConsoleReader in = new ConsoleReader(System.in); System.out.print("Ingrese el rango [0-100]: "); int rango = in.readInt(); String costo; if (rango >= 70) costo = "A"; else if (rango >= 60) costo = "B"; else if (rango >= 50) costo = "C"; else if (rango >= 40) costo = "D"; else costo = "F"; System.out.println("Costo = " + costo); } }

La misma técnica puede ser usada para situaciones en las que se quiera testear una serie de situaciones una después de otra if (B1) else if else if  else if else T

S1 (B2) S2 (B3) S3 (Bn) Sn

Ingeniería en Computación, Universidad de La Seren

71

Dr. Eric Jeltsch F.

Capítulo 4: Estructuras de Control

Podríamos tener un diagrama de flujo que lo representa,

Un tipo de dato bastante frecuente de usar en los códigos donde intervienen las decisiones son los tipos de datos booleanos, llamados boolean. La expresión booleana resp == 6048 puede ser evaluada para obtener uno de los valores de verdad true o false. Estos valores son llamados valores booleanos. Determinando un tipo de dato llamado boolean. Ud. puede crear variables de tipo boolean y asignarlo a una expresión Booleana, por ejemplo, boolean ok = (x > 0);

El operador == normalmente nunca es usado para testear si 2 string son los mismos, una alternativa es utilizar el método equalsIgnoreCase() st1.equalsIgnoreCase(st2)

que retorna true si st1 y st2 son dos string que consisten de los mismos caracteres, ya sea mayúscula o minúsculas, de otra manera será false. Como ejemplo mostramos un pequeño sistema de registro para alumnos. En este ejemplo se ha construido una clase llamada Alumno y un archivo para testear si la clase esta correcta para los datos que se le ingresan, al cabo del cual entrega una edición de los datos que Ud. ingreso pudiendo en on-line cambiar los datos que acabo de ingresar. Ingeniería en Computación, Universidad de La Seren

72

Dr. Eric Jeltsch F.

Capítulo 4: Estructuras de Control

Ejemplo 7 public class Alumno { private String idNumero; private String nombre; private String preGrado; private int anhos; private boolean estaRegistrado; /* alumno se ha registrado. */ public void registro() { estaRegistrado = true; } /* alumno NO se ha registrado. */ public void desregistro() { estaRegistrado = false; } /* Return true si el alumno se ha registrado, sino return false. */ public boolean tieneRegistro() { return estaRegistrado; } /* Editar los detalles del alumno. */ public void edit(ConsoleReader input) { System.out.print("ID numero (" + idNumero +") " ); String replica = input.readLine(); if (! replica.equals("")) idNumero = replica; System.out.print("Nombre (" + nombre + ") "); replica = input.readLine(); if (! replica.equals("")) nombre = replica; System.out.print("Programa de pregrado (" + preGrado + ") "); replica = input.readLine(); if (! replica.equals("")) if (replica.equals("Ing. Civil") || replica.equals("Ing. Alimentos") || replica.equals("Ing. Computacion") || replica.equals("Ped. Matematicas")) preGrado = replica; else System.out.println("programa de pregrado desconocido."); System.out.print("Años (" + anhos + ") "); replica = input.readLine(); if (! replica.equals("")) anhos = Integer.parseInt(replica); if (estaRegistrado) System.out.print("Esta registrado (si) "); else System.out.print("Esta registrado (no) "); replica = input.readLine(); if (! replica.equals("")) if (replica.equals("si")) estaRegistrado = true; Ingeniería en Computación, Universidad de La Seren

73

Dr. Eric Jeltsch F.

Capítulo 4: Estructuras de Control else if (replica.equals("no")) estaRegistrado = false; else System.out.println("Replica no entendida."); }

//los datos de pregrado, años y nombre no son cambiados. /* Crea un nuevo alumno con el ID numero dado, nombre y pregrado. Los años son seteados a 1. Serán registrado como no registrados. */ public Alumno(String id, String nm, String preG) { idNumero = id; nombre = nm; preGrado = preG; anhos = 1; estaRegistrado = false; } }//end class Alumno

Observar que Test Alumno es una nueva clase pública la cual invoca a Alumno y ConsoleReader. TestAlumno esta guardado en archivo con nombre TestAlumno.java, independiente de la clase Alumno. Pero si en el mismo directorio donde se reconocen. public class TestAlumno { /* Lee detalles de los alumnos. Crea el correspondiente objeto Alumno, y edita los detalles del objeto. */ public static void main(String[] args) { /* Crea ConsoleReader para leer el tipo de usuario. */ ConsoleReader in = new ConsoleReader(System.in); /* Crea el Alumno. */ System.out.println ("Cuál es el número ID del alumno(a)?"); String i = in.readLine(); System.out.println ("Cuál es el nombre del alumno(a)?"); String n = in.readLine(); System.out.println ("Pregrado al que pertenece el alumno(a)?"); String d = in.readLine(); Alumno st = new Alumno(i,n,d); System.out.println(); System.out.println("Editar los detalles del alumno."); st.edit(in); System.out.println(); } }

Aquí se ve la salida posible al programa anterior, llamado Test Alumno.java con la clase Alumno en el archivo Alumno.java, además de la clase ConsoleReader.java

Ingeniería en Computación, Universidad de La Seren

74

Dr. Eric Jeltsch F.

Capítulo 4: Estructuras de Control

Cuál es el número ID del alumno(a)? 9912345 Cuál es el nombre del alumno(a)? Alicia Lobos Pregrado al que pertenece el alumno(a)? Ing. Computacion Editar los detalle del alumno. ID numero (9912345) 9912346 Nombre (Alicia Lobos) Programa de pregrado(Ing. Computacion) Años (1) 2 Esta registrado(no) Si

Algunas expresiones booleanas son: = = !=
=

igual no igual menor que menor o igual a mayor que mayor o igual a

Justamente algunas expresiones aritméticas pueden ser construídas de una forma muy simple usando operadores aritméticos, tales como, +, , , etc. Si B1 y B2 son expresiones Booleanas. operador B1 && B2 B1 || B2 ! B1

hace B1 and B2 B1 or B2 not B1

Expresiones cuyo resultado están basado en la lógica Boolena, por ejemplo, B1 && B2 es true si B1 y B2 son ambos true, de otra manera es false. Cuando Java evalúa B1 && B2, evaluara primero B1. Si B1 es false no evaluara B2, pues esta “condenado” a ser false. Un análisis similar se hace con los otros conectivos. La expresión ! B1 será true si B1 es false, y será false si B1 es true. Una expresión de este tipo, n >= 0 && n< 10 || n >= 20 && n < 30

Java lo interpreta así, ((n>=0) && (n=20) && (n0): "); int i2 = in.readInt(); System.out.println (i1 + " elevado a " + i2 + " = " + power(i1,i2)); } /* Si p>=0, return n elevado a p. */ private static int power(int n, int p) { if (p == 0) return 1; else return power(n,p-1)*n; } }

Lo que realiza este programa es lo siguiente, así se visualiza su interacción con el usuario. Ingrese el primer entero: 3 Ingrese el segundo entero(>0): 5 3 elevado a 5

= 243

Suponga ahora que el programa está siendo ejecutado y la entrada por usuario es 2 y 4. Luego el método main es llamado, el usuario ingresa los dos valores, luego Java llamará a power(2,4) para encontrar la solución y respuesta, notar que la función está definida como método. En la primera llamada al método power el parámetro valor es n = 2 y p = 4. En este caso la segunda declaración return en el cuerpo del método será realizada, esto significa que Java evaluará la expresión power(n,p-1)*n, y entonces power(2,3) será evaluado. Se tiene, power(2,4)→ power(2,3). La siguiente vez que power es llamado pasa lo mismo, esta vez power(2,2) será llamada y el diagrama queda, power(2,4) → power(2,3) → power(2,2). Ingeniería en Computación, Universidad de La Seren

83

Dr. Eric Jeltsch F.

Capítulo 4: Estructuras de Control

Similarmente cuando power(2,2) es realizada llamará a power(2,1). Y cuando power(2,1) se realice, llamara a power(2,0). power(2,4) → power(2,3) → power(2,2) → power(2,1) → power(2,0). Aquí la cadena se detiene pues power(2,0) es realizado y va al primer return y se ejecuta. Así, power(2,0) retorna el valor 1, el que será usado en la ejecución de power(2,1), entregando el valor 12, que es 2, el que será usado en la ejecución de power(2,2), entregando el valor 4, y así sucesivamente. En general, podemos ver que si power(n,p) es realizada, con p0, la cadena completa contendrá p+1 llamadas a power, siendo la última llamada la que entrega 1. Todos los otros entregan n – veces el valor retornado por el siguiente. Las llamadas a power(n,p) entregan np. Vea el diagrama

No digo que este proceso sea rápido, pero si es sencilla su implementación para calcular np. Si p < 0 la cadena seguirá por siempre. Luego un código para calcular np, donde p  0, deberá tener probablemente algo parecido a esto. int resp = 1; for (int i = 0; i < p; i++) resp = resp * n;

En general, cualquier método recursivo puede ser escrito usando código no-recursivo. Otro ejemplo típico es el factorial de un número entero. Ejemplo 14 public class FactorialTest { // Cálculo del factorial de un número public static long factorial(int n) { if (n == 0) return 1; else return n * factorial(n-1); } public static void main(String[] args) { ConsoleReader in = new ConsoleReader(System.in); int numero; long fac; Ingeniería en Computación, Universidad de La Seren

84

Dr. Eric Jeltsch F.

Capítulo 4: Estructuras de Control

do { System.out.print("Ingrese el Número:"); numero = in.readInt(); } while (numero < 0 || numero > 25); fac = factorial(numero); System.out.println("\nEl factorial de " + numero + " es: " + fac); } }

Ingeniería en Computación, Universidad de La Seren

85

CAPITULO5 Excepciones y Flujo de Datos (Exceptions y Streams) Mensajes de error enviados por el compilador. Los humanos podemos tolerar errores ortográficos y gramaticales, pero los computadores no, y por esta razón el compilador Java cumple con su labor de denunciar este tipo de errores, identificando la línea y dando una corta explicación. Por ejemplo, aquí tenemos un programa que tiene varios errores. public class test { public static main(String[] args) { System.out.println(Hello!) }

Almacenemos el programa en Test.java y compilemoslo. El compilador replica, con varios errores de mensaje, el primero de ellos es C:\Documents and Settings\usuario\Escritorio\POO\POO_web_CD\Java_poo\Libro_Base_java\test.jav a:2: invalid method declaration; return type required { public static main(String[] args) ^

a) Estableciendo que existe un error en la línea 2 del programa y que se ubica aproximadamente en la posición marcada con ^. No nos dice exactamente cual es el problema, pero si nos invita a reflexionar respecto de la sintaxis de un programa. En este caso particular hemos olvidado la palabra clave void. C:\Documents and Settings\usuario\Escritorio\POO\POO_web_CD\Java_poo\Libro_Base_java\test.jav a:3: ')' expected { System.out.println(Hola!) ^

b) Luego el compilador reporta otro error en la línea 3 del programa y que se ubica aproximadamente en la posición marcada con ^. Lo que nos ayuda a ver con mayor preocupación que pasa en ese segmento de programa, y notamos que al escribir la palabra. Hola!, hemos olvidado escribirlo entre comillas. C:\Documents and Settings\usuario\Escritorio\POO\POO_web_CD\Java_poo\Libro_Base_java\test.jav a:4: ';' expected } ^

c) El compilador reporta otro error en la línea 4 del programa y que se ubica aproximadamente en la posición marcada con ^. Y notamos que nos falto cerrar una declaración con ;

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

C:\Documents and Settings\usuario\Escritorio\POO\POO_web_CD\Java_poo\Libro_Base_java\test.jav a:5: '}' expected ^ 4 errors Herramienta completada con código de salida 1

d) El compilador reporta otro error en la línea 5 del programa y que se ubica aproximadamente en la posición marcada con ^. Y notamos que nos falto cerrar un paréntesis, con un semicolon } Desafortunadamente, el compilador no es perfecto en detectar todos los errors gramaticales en una primera leída, es así como se require compilarlos e ir modificando el código del programa, hasta que quede libre de errores, no obstante el compilador no podrá hacer nada frente a un error semántico. Para completar este segmento digamos que este es un típico error para cuando una clase está carente de una clase principal para ser testeada.

Para mayor consulta dirigirse a The Java Language Specification, de J. Gosling, B. Joy, y G. Steele, Addison Wesley Publishing, 1996, para la definición del lenguaje Java. Diagnostico de los errores en Expresiones y Variables Expresiones y variables le dan a un programa más potencia, pero al mismo tiempo ofrecen la oportunidad de generar más errores. Los errores en este sentido pueden ser de dos formas: 

Errores relacionados con la gramática, contexto (tipo de datos), que el compilador Java puede detectar, son llamados: errores en tiempo de compilación.



Errores que ocurren para cuando el programa es ejecutado, deteniendose su ejecución en forma temprana, son llamados errores en tiempo de ejecución o excepciones.

Si consideramos el programa public class Test1{ public static void main(String[] args) { System.out.println( (1+2(*3 );//que desea? System.out.println(Hola!); } }

a) vemos que el compilador notifica y anuncia: C:\Documents and Settings\usuario\Escritorio\POO\POO_web_CD\Java_poo\Libro_Base_java\Test1.java: 3: ')' expected System.out.println( (1+2(*3 ); ^ Ingeniería en Computación, Universidad de La Seren

87

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

b) Si consideramos ahora el programa, detecta un problema en la definición del tipo de dato. public class Test1{ public static void main(String[] args) { string s;//basta con saber que el tipo de dato es String } }

C:\Documents and Settings\usuario\Escritorio\POO\POO_web_CD\Java_poo\Libro_Base_java\Test1.java: 4: cannot resolve symbol symbol : class string location: class Test1 string s; ^ C:\Documents and Settings\usuario\Escritorio\POO\POO_web_CD\Java_poo\Libro_Base_java\Test1.java: 3: operator + cannot be applied to int,boolean System.out.println(3 + true); ^

la explicación del compilador es elocuente, es decir enteros con boolenos no se entienden. public class test { public static void main(String[] args) int i=0; System.out.println(1/i); System.out.println("Hola!"); } }

{

tras el proceso natural de compilación podrá ver que el compilador no anuncia ningún tipo de problemas. Sin embargo, en la ejecución dice lo que se muestra.

este es un típico error en tiempo de ejecución, o también llamado una exception. Esto surgió cuando un programa usa tipos de datos incorrectos como argumentos del programa. No obstante si declara double i=0; en la ejecución saldrá

c) Otro ejemplo, surge para cuando se desea ejecutar un programa Java pero con varios parámetros desde la consola. Ingeniería en Computación, Universidad de La Seren

88

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

public class test { public static void main(String[] args) { int i = new Integer(args[0]).intValue(); System.out.println(1 / i); System.out.println("Hola!"); } }

El mensaje de error fue gatillado por la línea 3, y fue generado por la creación de un objeto Integer en la línea, siendo que la entrada de datos es un carácter, en este caso “a”. Finalmente, mostremos algunos errores que no son detectados ni por el compilador de Java, ni por su intérprete. Por ejemplo, se imprimen las variables x e y que son la misma. La declaración pasa la inspección del compilador Java, ahora realiza su ejecución y si Ud. espera ver ya sea un true o un false verá que surge un resultado, 7. public class test { public static void main(String[] args) int x = 3; int y = 7; System.out.println(x = y); System.out.println("Hola!"); } }

Ingeniería en Computación, Universidad de La Seren

{

89

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

La razón es que x = y es una asignación y no un test para igualdad, como (x = = y). La declaración, System.out.println(x = y), asigna y's valor a x's y lo imprime. Luego de haber visto esta serie de errores podrá formarse una idea, de lo que se trata este capítulo y que se refiere a complementar y reforzar el uso de excepciones, en donde Java posee una forma de tratar los errores en tiempo de ejecución. Además veremos como leer desde el teclado sin usar la clase que se le ha pedido “prestada” a Horstmann‟s llamada ConsoleReader, y como leer y escribir archivos de texto, además de como hacer uso de los parámetros que todo método main posee. Excepciones Java tiene un especial mecanismo para tratar errores en tiempo de ejecución. Suponga que escribe algún código que puede tener errores cuando lo ejecuta. Por ejemplo, si una cierta variable se refiriese a un objeto, y un error ocurre si la variable contiene null. Entonces puede Ud. insertar una declaración que arroja una excepción (throws and exception) si la condición de error ocurre. Veamos 2 situaciones. 1. Crear un objeto que describe la condición de error, usualmente llamada un objeto exception. (Ella pertenece a la clase Throwable, y estará ya sea en la subclase Error, si es un serio error del sistema, o en la subclase Exception, si ocurrió el error en el tiempo de ejecución normal.) 2. Esto causa que el interprete se detenga en la secuencia de declaraciones en donde ocurrió el error y comience a buscar una clausuala catch que ha sido escrita para responder al error apropiadamente, es decir, desplegando un window que le informa al usuario que hacer en lo sucesivo. (Como buscar la clausula catch se describirá posteriormente.) Si el interprete no puede encontrar una clausula disponible catch, el programa se detiene y Java desplegara un mensaje de error por defecto en la ventana DOS. Esto origina el nombre de excepciones y una lista de todos los métodos que están siendo ejecutados actualmente. Las excepciones son a menudo atrapadas o arrojadas por el mismo Java, ya sea por uno de los métodos de librería, o por un interprete, es decir, cuando encuentra algo el mismo trata de accesar a un array de elementos con un valor del indice fuera del rango correcto de valores. En este caso, la excepcion será una IndexOutOfBoundsException. Una cláusula catch es parte de una declaración try-catch y tiene la forma siguiente. try { Declaraciones catch (EXCEPCION1 e1) { Declaraciones } catch (EXCEPCION2 e2) { Declaraciones finally { Declaraciones } Ingeniería en Computación, Universidad de La Seren

90

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

La última parte finally clausula es por lo general omitida. Cuando el interprete obedece la declaración try-catch, ella ejecuta la DECLARACION try normalmente. Si ninguna excepcion es arrojada, eso es todo cuanto la declaración try-catch hace. Si una excepcion es arrojada, el interprete partira buscando para una try-clausula que sea obedecida para cuando la excepcion fue arrojada. Por supuesto la declaración try en la declaración try-catch fue obedecida, pero puede haber otra declaración try-catch más cerca de donde ocurrió el error. El intérprete entonces buscará el más interno, llamaremos a la declaración que produjo el error S0. Primero el intérprete mira dentro del cuerpo del método que contiene S0. Si encuentra que S0 está dentro de una try, toma una. Si hay dos o más declaraciones try anidadas que contienen a S0, toma la más interna. Si S0 no está al interior de una try, el intérprete va a la declaración S1 que llamó el método que contiene S0. Entonces empieza buscando la catch más interna que contiene S1. Si no puede encontrar uno en ese cuerpo del método, va a la declaración S2 llamando el método que contiene S1. Y así sucesivamente. Aquí se muestra un programa que contiene una declaración try-catch. El programa lee una serie de valores de punto flotante ingresados por el usuario, y se detiene cuando lee la palabra „fin‟. Suma los números y al mismo tiempo cuenta cuantos números son, finalmente, divide la suma de los número por el contador generando así el promedio de los números ingresados, el cual es desplegado en pantalla. El programa chequea si ve en la línea la palabra „fin‟. La línea es leída usando readLine. Si ella no tiene „fin‟, el programa procura convertirla en número usando el metodo Double.parseDouble. Si por error de tipeado, el usuario tipea algo que no es un número o la palabra „fin‟, entonces una NumberFormatException será lanzada. Si no es capturado el programa despliega un mensaje de error por defecto y para. Una declaración try-catch ha sido insertada en esta versión del programa para capturar las excepciones, y así evitar el mensaje de error. La clausula try incluye la llamada a Double.parseDouble, y la acción que continua para cuando el número esta correcto. La clausula catch justamente despliega un simple error de mensaje, y entonces el programa esta habilitado para realizar su tarea. Ejemplo 1 public class Promedio1 { /* Lee números flotante ingresados por el usuario y entrega el promedio. (Version que usa ConsoleReader.) */ public static void main(String[] args) { ConsoleReader usuario = new ConsoleReader(System.in); /* Lee y agrega los valores, y cuenta cuantos son. */ double sum = 0; int cuanTos = 0; System.out.println("Ingrese los datos."); while (true) { String linea = usuario.readLine(); Ingeniería en Computación, Universidad de La Seren

91

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

if (linea.equals("fin")) break; try /* protección de código, que podría lanzar una excepción dentro de try, pues este segmento de código podría causar una excepción, si no existen problemas continue, sino*/ {

double siguiente = Double.parseDouble(linea); sum = sum + siguiente; cuanTos++;

} catch (NumberFormatException e) /* Atrape la excepción, haciendo una prueba para manejar una excepción dentro de catch*/ { System.out.println ("Ingreso NO reconocido, intentelo de nuevo!."); } } /* el promedio. */ if (cuanTos > 0) System.out.println ("El valor promedio es = " + sum/cuanTos); else System.out.println("Sin resultado."); } }

También como excepciones producidas por Java, puede forzar una excepcion para ser arrojada mediante la declaración throw . Esta clausula indica que algún código en el cuerpo de su método podría lanzar una excepción, para tal efecto simplemente agregar la palabra throw después del nombre del método pero antes de abrir el bloque. Por ejemplo, public boolean miMetodo(int x, int y) trows AnException {

o más simple seguida por la referencia a un objeto excepcion. Por ejemplo, throw new NumberFormatException();

Note que un constructor es usado para crear el objeto exception aquí. Existen muchos tipos de excepciones definidas en la librería. Para encontrarlas todas vea la clase Exception y sus subclases. También, puede Ud. definir sus propias clases exccepcion extendiendo la clase Exception. Leer desde el teclado Cuando un programa Java lee la entrada, usa un objeto de algún tipo para manejar la entrada. El objeto será conectado a la fuente de la entrada, es decir la entrada fuente, me refiero a el teclado o archivo de texto. En términos de leer valores de entrada desde la fuente usamos métodos pertenecientes a ese objeto. El objeto ConsoleReader el cual hemos usado durante el curso para leer desde el teclado es un típico ejemplo de un objeto que maneja la entrada.

Ingeniería en Computación, Universidad de La Seren

92

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

El objeto que maneja la entrada será llamada InputStream o un Reader. La diferencia depende sobre que valores produce para cuando lea los caracteres. Un InputStream returns un 8-bit byte cada vez que lea un carácter, que es como el sistema lo representa. Un Reader returns 16bit caracteres. Esta es la forma estandar que Java representa caracteres, usando caracteres de código llamados unicode. Cada vez que se crea un objeto ConsoleReader, hacemos uso de otro objeto llamado System.in. Esto es un InputStream conectado directamente al teclado. InputStreams tiene varios métodos asociados con ellos, pero solamente uno puede ser usado para leer la entrada que es read que lee 8-bit byte. El siguiente diagrama representa el objeto System.in conectado al teclado, con la información que fluye del teclado, keyboard  System.in

Java posee clases llamadas InputStreamReader que consiste de objetos que producen los caracteres 16-bit unicode usados por Java. Existe un constructor que puede convertir un InputStream en un InputStreamReader. Ud. deberá darle InputStream como parametro, y el creara el InputStreamReader. Por ejemplo, la declaración siguiente construira una InputStreamReader conectado a System.in. InputStreamReader lector = new InputStreamReader(System.in);

Ud. puede incluir un segundo parámetro para especificar un decodificador noestandar para devolver bytes en caracteres unicode. Sin el segundo parametro, el InputStreamReader usará un decodificador estandar, el cual es satisfactorio para usos o propósitos normales. Lo mismo es posible para la salida. Aquí esta el diagrama de InputStreamReader definido anteriormente. Se obtiene 8-bit bytes desde el teclado, usando System.in, convirtiéndolos en caracteres de 16-bit. teclado  System.in  InputStreamReader

Un InputStreamReader tiene un método read que entrega un carácter simple. Esto sería posible de usarse para cuando escriba métodos que usan números reales, líneas de texto, etc. Sin embargo, un conveniente punto de partida es un objeto, el cual puede leer una linea de caracteres ala vez. Existen 2 tipos de objetos que pueden hacer uso de ellos. Uno es llamado BufferedReader y el otro es LineNumberReader. Ambos tienen un método readLine que retorna la siguiente línea de entrada. Ud, puede convertir un InputStreamReader en BufferedReader. Usualmente se hace mediante constructores. Por ejemplo, BufferedReader usuario = new BufferedReader (new InputStreamReader(System.in)); Ingeniería en Computación, Universidad de La Seren

93

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

La declaración se vé como sigue, teclado  System.in  InputStreamReader  BufferedReader

Ejemplo 2 Un programa que pregunta por la dimensión del cuadrado y entrega lo solicitado. Si le ingresa el valor 5, vera la figura: ***** * * * * * * ***** import java.io.*; public class Ejerc5{ public static void main(String args[]) throws IOException { int tam; BufferedReader din; din = new BufferedReader( new InputStreamReader(System.in)); System.out.println("Cuadrado"); System.out.println("========"); while (true) { System.out.print("Largo del lado [1-20,0=Fin]: "); tam = Integer.parseInt(din.readLine()); if (tam < 1) { break; } else if (tam java miProg

el Java interprete obtendrá la clase compilada miProg.class y se dirige a unos de los métodos main , el cual obedecera. En vez de este simple comando podemos tipear el comando Ingeniería en Computación, Universidad de La Seren

107

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

java

seguido con algunos argumentos de caracteres llamados command line arguments. Por ejemplo, java miProg data.txt hola.dat

command line arguments Un command line argument puede ser cualquier string de caracteres. Una lista de command line arguments se pasarán del método main en la forma de un array de strings. Si son dos argumentos como en el ejemplo anterior entonces el arreglo es de 2 elementos los que hacen referencia a 2 strings. Este array es parámetro de tipo String[] , que todo método main posee. Si suponemos que, en el encabezado del método main es, public static void main(String[] args)

y suponemos que el interprete Java es dado la línea de comando con 2 argumentos , como antes se mencionaba, entonces un parametro variable llamado args sera creado que contenga una referencia a los 2 elementos del array que anteriormente hacían referencia al strings data.txt y hola.dat.

data.txt args

hola.dat

Con los argumentos strings presentados en esta forma, el método main puede procesarlo en el sentido que el programador decida. Por ejemplo, puede usar la expresión args.length

para denotar el número de argumentos. Y los argummentos individuales pueden ser referidos como args[0], args[1], etc. Un ejemplo de esta idea esta dado por la siguiente aplicación que convierte en mayúscula todo el texto de un archivo. El archivo es leído mediante un flujo de entrada almacenado en buffer, y se lee un carácter a la vez. Una vez convertido en mayúscula, el carácter se envía a un archivo temporal por medio de un flujo de entrada almacenado en buffer. Los objetos File se usan en vez de las cadenas para indicar los archivos involucrados, lo cual hace posible cambiarles el nombre y borrarlos según se necesite.

Ingeniería en Computación, Universidad de La Seren

108

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

Ejemplo 7 import java.io.*; public class todoMayusDemo { public static void main(String[] arguments) { todoMayus may = new todoMayus(arguments[0]); may.convert(); } } class todoMayus { String nombreFuente; todoMayus(String nombreArg) { nombreFuente = nombreArg; } void convert() { try { // Crea los objetos archivos(File) File nombre = new File(nombreFuente); File temp = new File( nombreFuente + ".tmp"); // Crea una entrada stream FileReader fr = new FileReader(nombre); BufferedReader in = new BufferedReader(fr); // Crea la salida stream FileWriter fw = new FileWriter(temp); BufferedWriter out = new BufferedWriter(fw); boolean eof = false; int inChar = 0; do { inChar = in.read(); if (inChar != -1) { char outChar = Character.toUpperCase( (char)inChar ); out.write(outChar); } else eof = true; } while (!eof); in.close(); out.close(); boolean borrar = nombre.delete(); if (borrar) temp.renameTo(nombre); } catch (IOException e) { System.out.println("Error -- " + e.toString()); } catch (SecurityException se) { System.out.println("Error -- " + se.toString()); } } }

Ingeniería en Computación, Universidad de La Seren

109

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

Excepciones y Flujo de Datos (Exceptions y Streams) Mensajes de error enviados por el compilador. Los humanos podemos tolerar errores ortográficos y gramaticales, pero los computadores no, y por esta razón el compilador Java cumple con su labor de denunciar este tipo de errores, identificando la línea y dando una corta explicación. Por ejemplo, aquí tenemos un programa que tiene varios errores. public class test { public static main(String[] args) { System.out.println(Hello!) }

Almacenemos el programa en Test.java y compilemoslo. El compilador replica, con varios errores de mensaje, el primero de ellos es C:\Documents and Settings\usuario\Escritorio\POO\POO_web_CD\Java_poo\Libro_Base_java\test.java:2 : invalid method declaration; return type required { public static main(String[] args) ^

a)

Estableciendo que existe un error en la línea 2 del programa y que se ubica aproximadamente en la posición marcada con ^. No nos dice exactamente cual es el problema, pero si nos invita a reflexionar respecto de la sintaxis de un programa. En este caso particular hemos olvidado la palabra clave void. C:\Documents and Settings\usuario\Escritorio\POO\POO_web_CD\Java_poo\Libro_Base_java\test.java:3 : ')' expected { System.out.println(Hola!) ^

b)

Luego el compilador reporta otro error en la línea 3 del programa y que se ubica aproximadamente en la posición marcada con ^. Lo que nos ayuda a ver con mayor preocupación que pasa en ese segmento de programa, y notamos que al escribir la palabra Hola!, hemos olvidado escribirlo entre comillas.

C:\Documents and Settings\usuario\Escritorio\POO\POO_web_CD\Java_poo\Libro_Base_java\test.jav a:4: ';' expected } ^

c)

El compilador reporta otro error en la línea 4 del programa y que se ubica aproximadamente en la posición marcada con ^. Y notamos que nos falto cerrar una declaración con ;

Ingeniería en Computación, Universidad de La Seren

110

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

C:\Documents and Settings\usuario\Escritorio\POO\POO_web_CD\Java_poo\Libro_Base_java\test.jav a:5: '}' expected ^ 4 errors Herramienta completada con código de salida 1

d)

El compilador reporta otro error en la línea 5 del programa y que se ubica aproximadamente en la posición marcada con ^. Y notamos que nos falto cerrar un paréntesis, con un semicolon }.

Desafortunadamente, el compilador no es perfecto en detectar todos los errors gramaticales en una primera leída, es así como se require compilarlos e ir modificando el código del programa, hasta que quede libre de errores, no obstante el compilador no podrá hacer nada frente a un error semántico. Para completar este segmento digamos que este es un típico error para cuando una clase está carente de una clase principal para ser testeada.

Para mayor consulta dirigirse a The Java Language Specification, de J. Gosling, B. Joy, y G. Steele, Addison Wesley Publishing, 1996, para la definición del lenguaje Java.

Diagnóstico de los errores en Expresiones y Variables Expresiones y variables le dan a un programa más potencia, pero al mismo tiempo ofrecen la oportunidad de generar más errores. Los errores en este sentido pueden ser de dos formas: 

Errores relacionados con la gramática, contexto (tipo de datos), que el compilador Java puede detectar, son llamados: errores en tiempo de compilación.



Errores que ocurren para cuando el programa es ejecutado, deteniendose su ejecución en forma temprana, son llamados errores en tiempo de ejecución o excepciones.

Si consideramos el programa public class Test1{ public static void main(String[] args) { System.out.println( (1+2(*3 );//que desea? System.out.println(Hola!); } }

Ingeniería en Computación, Universidad de La Seren

111

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

a) vemos que el compilador notifica y anuncia: C:\Documents and Settings\usuario\Escritorio\POO\POO_web_CD\Java_poo\Libro_Base_java\Test1.java:3: ')' expected System.out.println( (1+2(*3 ); ^

b) Si consideramos ahora el programa, detecta un problema en la definición del tipo de dato. public class Test1{ public static void main(String[] args) { string s;//basta con saber que el tipo de dato es String } } C:\Documents and Settings\usuario\Escritorio\POO\POO_web_CD\Java_poo\Libro_Base_java\Test1.java:4: cannot resolve symbol symbol : class string location: class Test1 string s; ^ C:\Documents and Settings\usuario\Escritorio\POO\POO_web_CD\Java_poo\Libro_Base_java\Test1.java:3: operator + cannot be applied to int,boolean System.out.println(3 + true); ^

la explicación del compilador es elocuente, es decir enteros con boolenos no se entienden. public class test { public static void main(String[] args) int i=0; System.out.println(1/i); System.out.println("Hola!"); } }

{

tras el proceso natural de compilación podrá ver que el compilador no anuncia ningún tipo de problemas. Sin embargo, en la ejecución dice lo que se muestra.

este es un típico error en tiempo de ejecución, o también llamado una exception. Esto surgió cuando un programa usa tipos de datos incorrectos como argumentos del programa. No obstante si declara double i=0; en la ejecución saldrá

Ingeniería en Computación, Universidad de La Seren

112

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

c) Otro ejemplo, surge para cuando se desea ejecutar un programa Java pero con varios parámetros desde la consola. public class test { public static void main(String[] args) { int i = new Integer(args[0]).intValue(); System.out.println(1 / i); System.out.println("Hola!"); } }

El mensaje de error fue gatillado por la línea 3, y fue generado por la creación de un objeto Integer en la línea, siendo que la entrada de datos es un carácter, en este caso “a”.

Ingeniería en Computación, Universidad de La Seren

113

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

Finalmente, mostremos algunos errores que no son detectados ni por el compilador de Java, ni por su intérprete. Por ejemplo, se imprimen las variables x e y que son la misma. La declaración pasa la inspección del compilador Java, ahora realiza su ejecución y si Ud. espera ver ya sea un true o un false verá que surge un resultado, 7. public class test { public static void main(String[] args) int x = 3; int y = 7; System.out.println(x = y); System.out.println("Hola!"); } }

{

La razón es que x = y es una asignación y no un test para igualdad, como (x = = y). La declaración, System.out.println(x = y), asigna y's valor a x's y lo imprime. Luego de haber visto esta serie de errores podrá formarse una idea, de lo que se trata este capítulo y que se refiere a complementar y reforzar el uso de excepciones, en donde Java posee una forma de tratar los errores en tiempo de ejecución. Además veremos como leer desde el teclado sin usar la clase que se le ha pedido “prestada” a Horstmann‟s llamada ConsoleReader, y como leer y escribir archivos de texto, además de como hacer uso de los parámetros que todo método main posee. Excepciones Java tiene un especial mecanismo para tratar errores en tiempo de ejecución. Suponga que escribe algún código que puede tener errores cuando lo ejecuta. Por ejemplo, si una cierta variable se refiriese a un objeto, y un error ocurre si la variable contiene null. Entonces puede Ud. insertar una declaración que arroja una excepción (throws and exception) si la condición de error ocurre. Veamos 2 situaciones. 1.

Crear un objeto que describe la condición de error, usualmente llamada un objeto exception. (Ella pertenece a la clase Throwable, y estará ya sea en la subclase Error, si es un serio error del sistema, o en la subclase Exception, si ocurrió el error en el tiempo de ejecución normal.)

2.

Esto causa que el interprete se detenga en la secuencia de declaraciones en donde ocurrió el error y comience a buscar una clausuala catch que ha sido escrita para responder al error apropiadamente, es decir, desplegando un window que le informa al usuario que hacer en lo sucesivo. (Como buscar la clausula catch se describirá posteriormente.) Si el interprete no puede encontrar una clausula disponible catch, el programa se detiene y Java desplegara un mensaje de error por defecto en la ventana DOS. Esto origina el nombre de excepciones y una lista de todos los métodos que están siendo ejecutados actualmente.

Ingeniería en Computación, Universidad de La Seren

114

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

Las excepciones son a menudo atrapadas o arrojadas por el mismo Java, ya sea por uno de los métodos de librería, o por un interprete, es decir, cuando encuentra algo el mismo trata de accesar a un array de elementos con un valor del indice fuera del rango correcto de valores. En este caso, la excepcion será una IndexOutOfBoundsException. Una cláusula catch es parte de una declaración try-catch y tiene la forma siguiente. try { Declaraciones catch (EXCEPCION1 e1) { Declaraciones } catch (EXCEPCION2 e2) { Declaraciones finally { Declaraciones }

La última parte finally clausula es por lo general omitida. Cuando el interprete obedece la declaración try-catch, ella ejecuta la declaración try normalmente. Si ninguna excepción es arrojada, eso es todo cuanto la declaración try-catch hace. Si una excepción es arrojada, el intérprete partira buscando para una try-clausula que sea obedecida para cuando la excepción fue arrojada. Por supuesto la declaración try en la declaración try-catch fue obedecida, pero puede haber otra declaración try-catch más cerca de donde ocurrió el error. El intérprete entonces buscará el más interno, llamaremos a la declaración que produjo el error S0. Primero el intérprete mira dentro del cuerpo del método que contiene S0. Si encuentra que S0 está dentro de una try, toma una. Si hay dos o más declaraciones try anidadas que contienen a S0, toma la más interna. Si S0 no está al interior de una try, el intérprete va a la declaración S1 que llamó el método que contiene S0. Entonces empieza buscando la catch más interna que contiene S1. Si no puede encontrar uno en ese cuerpo del método, va a la declaración S2 llamando el método que contiene S1. Y así sucesivamente. Aquí se muestra un programa que contiene una declaración try-catch. El programa lee una serie de valores de punto flotante ingresados por el usuario, y se detiene cuando lee la palabra „fin‟. Suma los números y al mismo tiempo cuenta cuantos números son, finalmente, divide la suma de los números por el contador generando así el promedio de los números ingresados, el cual es desplegado en pantalla. El programa chequea si ve en la línea la palabra „fin‟. La línea es leída usando readLine. Si ella no tiene „fin‟, el programa procura convertirla en número usando el metodo Double.parseDouble. Si por error de tipeado, el usuario tipea algo que no es un número o la palabra „fin‟, entonces una NumberFormatException será lanzada. Si no es capturado el programa despliega un mensaje de error por defecto y para. Una declaración try-catch ha sido insertada en esta versión del programa para capturar las excepciones, y así evitar el mensaje de error. La clausula try incluye la llamada a Ingeniería en Computación, Universidad de La Seren

115

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

Double.parseDouble, y la acción que continua para clausula catch justamente despliega un simple error de

cuando el número esta correcto. La mensaje, y entonces el programa esta

habilitado para realizar su tarea. Ejemplo 1 public class Promedio1 { /* Lee números flotante ingresados por el usuario y entrega el promedio. (Version que usa ConsoleReader.) */ public static void main(String[] args) { ConsoleReader usuario = new ConsoleReader(System.in); /* Lee y agrega los valores, y cuenta cuantos son. */ double sum = 0; int cuanTos = 0; System.out.println("Ingrese los datos."); while (true) { String linea = usuario.readLine(); if (linea.equals("fin")) break; try /* protección de código, que podría lanzar una excepción dentro de try, pues este segmento de código podría causar una excepción, si no existen problemas continue, sino*/ {

double siguiente = Double.parseDouble(linea); sum = sum + siguiente; cuanTos++;

} catch (NumberFormatException e) /* Atrape la excepción, haciendo una prueba para manejar una excepción dentro de catch*/ { System.out.println ("Ingreso NO reconocido, intentelo de nuevo!."); } } /* el promedio. */ if (cuanTos > 0) System.out.println ("El valor promedio es = " + sum/cuanTos); else System.out.println("Sin resultado."); } }

También como excepciones producidas por Java, puede forzar una excepcion para ser arrojada mediante la declaración throw . Esta clausula indica que algún código en el cuerpo de su método podría lanzar una excepción, para tal efecto simplemente agregar la palabra throw después del nombre del método pero antes de abrir el bloque. Por ejemplo, public boolean miMetodo(int x, int y) trows AnException {

o más simple seguida por la referencia a un objeto excepcion. Por ejemplo, throw new NumberFormatException(); Ingeniería en Computación, Universidad de La Seren

116

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

Note que un constructor es usado para crear el objeto exception aquí. Existen muchos tipos de excepciones definidas en la librería. Para encontrarlas todas vea la clase Exception y sus subclases. También, puede Ud. definir sus propias clases exccepcion extendiendo la clase Exception. Leer desde el teclado Cuando un programa Java lee la entrada, usa un objeto de algún tipo para manejar la entrada. El objeto será conectado a la fuente de la entrada, es decir la entrada fuente, me refiero a el teclado o archivo de texto. En términos de leer valores de entrada desde la fuente usamos métodos pertenecientes a ese objeto. El objeto ConsoleReader el cual hemos usado durante el curso para leer desde el teclado es un típico ejemplo de un objeto que maneja la entrada. El objeto que maneja la entrada será llamada InputStream o un Reader. La diferencia depende sobre que valores produce para cuando lea los caracteres. Un InputStream returns un 8-bit byte cada vez que lea un carácter, que es como el sistema lo representa. Un Reader returns 16bit caracteres. Esta es la forma estandar que Java representa caracteres, usando caracteres de código llamados unicode. Cada vez que se crea un objeto ConsoleReader, hacemos uso de otro objeto llamado System.in. Esto es un InputStream conectado directamente al teclado. InputStreams tiene varios métodos asociados con ellos, pero solamente uno puede ser usado para leer la entrada que es read que lee 8-bit byte. El siguiente diagrama representa el objeto System.in conectado al teclado, con la información que fluye del teclado, keyboard  System.in

Java posee clases llamadas InputStreamReader que consiste de objetos que producen los caracteres 16-bit unicode usados por Java. Existe un constructor que puede convertir un InputStream en un InputStreamReader. Ud. deberá darle InputStream como parametro, y el creara el InputStreamReader. Por ejemplo, la declaración siguiente construira una InputStreamReader conectado a System.in. InputStreamReader lector = new InputStreamReader(System.in);

Ud. puede incluir un segundo parámetro para especificar un decodificador noestandar para devolver bytes en caracteres unicode. Sin el segundo parametro, el InputStreamReader usará un decodificador estandar, el cual es satisfactorio para usos o propósitos normales. Lo mismo es posible para la salida. Aquí esta el diagrama de InputStreamReader definido anteriormente.

Ingeniería en Computación, Universidad de La Seren

117

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

Se obtiene 8-bit bytes desde el teclado, usando System.in, convirtiéndolos en caracteres de 16-bit. teclado  System.in  InputStreamReader

Un InputStreamReader tiene un método read que entrega un carácter simple. Esto sería posible de usarse para cuando escriba métodos que usan números reales, líneas de texto, etc. Sin embargo, un conveniente punto de partida es un objeto, el cual puede leer una linea de caracteres ala vez. Existen 2 tipos de objetos que pueden hacer uso de ellos. Uno es llamado BufferedReader y el otro es LineNumberReader. Ambos tienen un método readLine que retorna la siguiente línea de entrada. Ud, puede convertir un InputStreamReader en BufferedReader. Usualmente se hace mediante constructores. Por ejemplo, BufferedReader usuario = new BufferedReader (new InputStreamReader(System.in));

La declaración se vé como sigue, teclado  System.in  InputStreamReader  BufferedReader

Ejemplo 2 Un programa que pregunta por la dimensión del cuadrado y entrega lo solicitado. Si le ingresa el valor 5, vera la figura: ***** * * * * * * ***** import java.io.*; public class Ejerc5{ public static void main(String args[]) throws IOException { int tam; BufferedReader din; din = new BufferedReader( new InputStreamReader(System.in)); System.out.println("Cuadrado"); System.out.println("========"); while (true) { Ingeniería en Computación, Universidad de La Seren

118

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

System.out.print("Largo del lado [1-20,0=Fin]: "); tam = Integer.parseInt(din.readLine()); if (tam < 1) { break; } else if (tam java miProg el Java interprete obtendrá la clase compilada miProg.class y se dirige a unos de los métodos main , el cual obedecera. En vez de este simple comando podemos tipear el comando java seguido con algunos argumentos de caracteres llamados command line arguments. Por ejemplo, java miProg data.txt hola.dat

command line arguments Un command line argument puede ser cualquier string de caracteres. Una lista de command line arguments se pasarán del método main en la forma de un array de strings. Si son dos argumentos como en el ejemplo anterior entonces el arreglo es de 2 elementos los que hacen referencia a 2 strings. Este array es parámetro de tipo String[] , que todo método main posee. Si suponemos que, en el encabezado del método main es, public static void main(String[] args)

y suponemos que el interprete Java es dado la línea de comando con 2 argumentos , como antes se mencionaba, entonces un parametro variable llamado args sera creado que contenga Ingeniería en Computación, Universidad de La Seren

132

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos

una referencia a los 2 elementos del array que anteriormente hacían referencia al strings data.txt y hola.dat. data.txt args

hola.dat

Con los argumentos strings presentados en esta forma, el método main puede procesarlo en el sentido que el programador decida. Por ejemplo, puede usar la expresión args.length

para denotar el número de argumentos. Y los argummentos individuales pueden ser referidos como args[0], args[1], etc. Un ejemplo de esta idea esta dado por la siguiente aplicación que convierte en mayúscula todo el texto de un archivo. El archivo es leído mediante un flujo de entradab almacenado en buffer, y se lee un carácter a la vez. Una vez convertido en mayúscula, el carácter se envía a un archivo temporal por medio de un flujo de entrada almacenado en buffer. Los objetos File se usan en vez de las cadenas para indicar los archivos involucrados, lo cual hace posible cambiarles el nombre y borrarlos según se necesite. Ejemplo 7 import java.io.*; public class todoMayusDemo { public static void main(String[] arguments) { todoMayus may = new todoMayus(arguments[0]); may.convert(); } } class todoMayus { String nombreFuente; todoMayus(String nombreArg) { nombreFuente = nombreArg; } void convert() { try { // Crea los objetos archivos(File) File nombre = new File(nombreFuente); File temp = new File( nombreFuente + ".tmp"); // Crea una entrada stream FileReader fr = new FileReader(nombre); BufferedReader in = new BufferedReader(fr); Ingeniería en Computación, Universidad de La Seren

133

Dr. Eric Jeltsch F.

Capítulo 5: Excepciones y Flujo de Datos // Crea la salida stream FileWriter fw = new FileWriter(temp); BufferedWriter out = new BufferedWriter(fw);

boolean eof = false; int inChar = 0; do { inChar = in.read(); if (inChar != -1) { char outChar = Character.toUpperCase( (char)inChar ); out.write(outChar); } else eof = true; } while (!eof); in.close(); out.close(); boolean borrar = nombre.delete(); if (borrar) temp.renameTo(nombre); } catch (IOException e) { System.out.println("Error -- " + e.toString()); } catch (SecurityException se) { System.out.println("Error -- " + se.toString()); } } }

Ingeniería en Computación, Universidad de La Seren

134

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

CAPÍTULO 6 Programación Orientada a Objetos en Java Hasta el momento hemos discutido una serie de conceptos de la programación orientada a objetos en Java, sin preocuparnos mayormente sobre el detalle de ciertas declaraciones, como por ejemplo, ¿Porqué main() en los programas antes escrito deben ser public y static?. La idea para entender la filosofía que está detrás de Java pasa por analizar y entender algunos conceptos de la POO. Por otra parte, en esta oportunidad pretendo que aprendan aplicar en java la POO, así como los fundamentos de la POO, y como ellos se visualizan en Java, como por ejemplo los conceptos de: clase, objeto, método, instancia, herencia, polimorfismo, constructor, interface, sobrecarga, etc. En resumen este segmento trata de introducirlo en los fundamentos que le harán tomar confianza con la POO. Un pequeño adelanto respecto de los conceptos de la POO es que la POO encapsula datos (atributos) y métodos en un objeto. Los objetos tienen la propiedad de ocultar la información. Ahora si Ud. ha programado en C, verá que es orientado a la acción, Java en cambio es orientada a objetos, esto significa que en C la unidad de programación son las funciones (en Java este tipo de estructuras se llaman métodos). No obstante, las funciones no desaparecen en Java, sino que ellas son encapsuladas como métodos con datos que se procesan al interior de la clase. La Fig.1, nos muestra cómo se ve en general un segmento de programa en Java. Declaración de clase public abstract final class Nombre_Clase extends Nombre_Clase implements lista_Interface {

Atributo type Nombre Atributo; Constructor public Nombre_Clase ( ) {//...} Método public hola (...) {//...}

Fig. 1 Ingeniería en Computación, Universidad de La Seren

135

Dr. Eric Jeltsch F.

Términos técnicos en POO -Agente -Progr. Visual -dynamic binding

Capítulo 6: Programación Orientada a Objetos

Características -Polimorfismo -Abstracción -Encapsulación -Persistencia

Mecanismos Básicos -Objeto -Mensaje y MétodosClase y ModeloHerencia

Fig. 2 La Fig. 2 muestra los pilares básicos de la orientación a objeto. Los programadores en Java se concentran en crear sus propias Clases, que son tipos definidos de programas o bien utilizar algunas para sus propios fines. Así por ejemplo, ya hemos usado la clase ConsoleReader en los ejemplos de las otras lecciones. Cada clase contiene datos, como también un conjunto de métodos que manipulan los datos. Observación: El modelamiento de grandes sistemas es exitoso en la medida que se haga asesorar por una herramienta de modelamiento. UML (Unified Modeling Language) es un lenguaje de programación gráfico útil para la descripción de diferentes aspectos en la modelación de un sistema orientado a objetos, en donde se pueden representar clases, objetos y su relación.

Clases y Objetos Una class (clase) es una estructura de programación en la que se pueden agrupar los datos de un objeto junto con los métodos que operan sobre ellos. En Ejemplo1, se declara una clase de nombre Empleado como Tipo, la que no posee métodos (por ahora). Formalmente una clase puede considerarse como una especificación 4-upla, por tener 4 componentes, en forma de variables con tipo y nombre. El modelo UML asociado a la clase, se muestra a continuación. En donde se han definido 4 atributos, dos de ellos pueden contener una cadena de caracteres (recordar que una cadena de caracteres es un objeto de la clase String), el otro es de tipo entero y finalmente un atributo de tipo boolean , el que puede ser verdadero o falso. Ejemplo 1 class Empleado { String apellido; String nombre; int rut; boolean esFemenino; }

Ingeniería en Computación, Universidad de La Seren

136

Dr. Eric Jeltsch F.

Empleado Apellido: String Nombre: String Rut: int EsFemenino: boolean

Capítulo 6: Programación Orientada a Objetos

objetoEmpleado: Empleado Apellido: Rojas Nombre: Lautaro Rut: 73881706 EsFemenino: false

Cada componente de este tipo es una clase_instancia de la clase Empleado, usualmente llamada instancia (instance en Inglés), las que usualmente se conocen como objetos. Un objeto es una variable de la clase, intuitivamente un objeto es una entidad del mundo real, por otra parte como ya lo mencionabamos un objeto es una variable (del tipo) de la clase, y los programadores lo conocen como una instancia (es decir, una ejemplificación concreta) de la clase y por ende deberá contener todas las componentes que tenga la clase. En este caso todo objeto de la clase Empleado deberá tener ejemplares de las 4-variables, como lo muestra la figura anterior. Para mayor información vea, http://java.sun.com/docs/books/tutorial/java/data/objects.html

Instancias de una Clase ¿Cómo entender el enunciado “la clase será instanciada”?. La concepción de nuevas instancias en una clase se realizan sintácticamente a través de la palabra new, y la forma de cómo llegar a las variables que tiene la clase se logran a través de la creación de este nuevo objeto seguido de un punto(.). Ejemplo 2 /*Incorpore Empleado.class a su directorio, o sino compile con el contenido de Empleado.java dentro de su archivo NuevaInstancia.java. */ class NuevaInstancia { public static void main(String args[]){ Empleado m; // Instancia: creación de un nuevo Objeto m = new Empleado(); // forma de escribir sobre las Instancia-variable: m.apellido = "Montes"; m.nombre = "Hugo"; m.rut = 11073; m.esFemenino = false; // leer las Instancia-variable: System.out.println("Apellido: " + m.apellido); System.out.println("Nombre: " + m.nombre); System.out.println("Numero Personal: " + m.rut); System.out.println("Hablamos de: " + (m.esFemenino ? "Sra." : "Sr.")); // le ponemos un segundo Objeto: Empleado n = new Empleado(); n.apellido = "Rojo"; Ingeniería en Computación, Universidad de La Seren

137

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos n.nombre = "Maria”; n.rut = 865; n.esFemenino = true; }

}

Constructores Al crear la instancia de un objeto, el programa habitualmente asigna valores iniciales a sus elementos de datos. Para simplificar la inicialización de los elementos del objeto, Java soporta una función o método especial llamado constructor, que se ejecuta de forma automática al crear la instancia. La función contructora es un método público que tiene el mismo nombre de la clase. Es necesario tener en cuenta que:  Un constructor tiene el mismo nombre que la clase,  Un constructor siempre se llama con la palabra clave new,  Los constructores pueden tener ceros o más parámetros,  Los constructores no devuelven ningún tipo en forma explícita. Por eso que la llamada a constructores, como también los métodos con tipo de resultado void entregan el resultado en la forma " return;”.Veamos el siguiente ejemplo. Ejemplo 3 class Empleado { String apellido; String nombre; int rut; boolean esFemenino; // Declaración de un Constructor: Empleado(String nn, String vn, int pn, boolean w) { apellido = nn; nombre = vn; rut = pn; esFemenino = w; } } class EjemploConstructor { public static void main(String args[]){ Empleado m,n; // Llamada al Constructor: m = new Empleado("Meyer", "Hans", 11073, false); n = new Empleado("Rojo", "Maria", 865, true); // leer las Instancia-variable: System.out.println("Apellido: " + m.apellido); System.out.println("Nombre: " + m.nombre); System.out.println("Numero Personal: " + m.rut); System.out.println("Hablamos de:" +(m.esFemenino ? "Sra.": "Sr.")); } }

Ingeniería en Computación, Universidad de La Seren

138

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

Variables en la clase En contrario a la instancia-variable existe también para una clase y para todo objeto de una clase un ejemplar, llamada variable de la clase, aún cuando la clase no tenga ninguna instancia. Esta variable es estática, y un ejemplo típico es un contador. Ejemplo 4 class Empleado { String apellido; String nombre; int rut; boolean esFemenino; // una variable de la clase,inicializada por 0. static int contador = 0; Empleado(String nn, String vn, int pn, boolean w) { apellido = nn;nombre = vn;rut = pn;esFemenino = w; contador++; } } class EjemploContador { public static void main(String args[]){ System.out.println("Contador: " + Empleado.contador); Empleado m1 = new Empleado("Montes","Hugo",11073,false); System.out.println("Contador: " + Empleado.contador); Empleado m2 = new Empleado("Rojo", "Maria", 865, true); System.out.println("Contador: " + Empleado.contador); } }

Clase como Tipo La clase Empleado puede variar, de manera que contenga una instancia-variable con nombre ascenso, que puede ser de tipo Empleado. Ejemplo 5 class Empleado { String apellido; String nombre; int rut; boolean esFemenino; // una clase como tipo en una instancia-variable Empleado ascenso; // Constructor: Empleado(String nn,String vn,int pn,boolean w,Empleado as) { apellido = nn; nombre = vn; rut = pn; esFemenino = w; ascenso = as; } }

Ingeniería en Computación, Universidad de La Seren

139

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

class EjemploClasecomoTipo { public static void main(String args[]){ Empleado m, jefe; // una clase como tipo variable local jefe = new Empleado("Rojo", "Martin", 341, false, null); m = new Empleado("Meyer", "Hans", 11073, false, jefe); } }

Expresiones para instanciar Las variables como Uds. notaron fueron inicializadas por: Empleado jefe = new Empleado("Soto","Martin",341,false,null); Empleado m = new Empleado("Meyer","Juan",11073,false,jefe);

Otra expresión un tanto más sofisticada pero igualmente válida es: Empleado m = new Empleado("Meyer", "Juan", 11073, false, new Empleado("Soto", "Martin", 341, false, null));

Es así como a través de los operadores = = y != pueden ser comparadas expresiones, tales como. Ejemplo 6 class CompararObjetos { public static void main(String args[]){ Empleado m1=new Empleado("Soto","Martin",341,false,null); Empleado m2=new Empleado("Soto","Martin",341,false,null); boolean b = (m1 == m2); // b tendra el valor "false". System.out.println(b); b = (null != null); // b tendrá el valor "false". } }

Métodos Instanciados Al interior de una clase cada declaración sin la palabra static describe un método instanciado. Ejemplo 7 class Empleado { String apellido; String nombre; int rut; boolean esFemenino; // Constructor: Empleado(String nn, String vn, int pn, boolean w){ apellido = nn; nombre = vn; rut = pn; esFemenino = w; } // un método Instanciado: void salida(){ System.out.print(esFemenino ? "Sra. " : "Sr. "); Ingeniería en Computación, Universidad de La Seren

140

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

System.out.print(apellido + " "); System.out.print(nombre); System.out.println(" (Rut: " + rut + ")"); } } class EjemploMetodoInstanciado { public static void main(String args[]){ Empleado m1 = new Empleado("Soto", "Martin", 341, false); Empleado m2 = new Empleado("Barrios", "Petra", 865, true); // dos llamadas al método instanciado: m1.salida(); m2.salida(); } }

La palabra clave this Al trabajar con objetos, a veces es necesario hacer referencia al objeto de la clase en sí. Por ejemplo, un método de clase puede requerir pasarse a sí mismo otra función, de la misma forma, un método puede necesitar devolver el objeto en sí a la función que lo llama, de manera que el solicitante sepa que objeto está manipulando. En estos casos es posible utilizar la palabra this para hacer referencia al objeto en sí. a) class Miembro { Miembro anterior; Miembro posterior; void ingreso(Miembro nuevo){ // pone "nuevo" detras de "this" en la cadena: if(nuevo != null){ this.posterior = nuevo; nuevo.anterior = this; } } }

b) class Empleado { String apellido; String nombre; int rut; boolean esFemenino; //Constructor: Empleado(String apellido, String nombre, int pn, boolean w){ this.apellido = apellido; // "this" es imprescindible this.nombre = nombre; // "this" es imprescindible int rut; boolean esFemenino; this.rut = pn; // "this" es imprescindible this.esFemenino = w; // "this" es imprescindible } }

Ingeniería en Computación, Universidad de La Seren

141

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

Métodos en las Clases Son como las variables en la clase, sin embargo es fácil darse cuenta de ella al reconocer la palabra clave static, también conocidos como métodos estáticos. Este tipo de método son globales que funcionan para la clase en general, y no solamente para una determinada instancia. Ejemplo 8 class Empleado { String apellido; String nombre; int rut; boolean esFemenino; static int contador = 0; // Constructor: Empleado(String nn, String vn, int pn, boolean w){ apellido= nn; nombre = vn; rut = pn; esFemenino = w; contador++; } // 2 métodos en la clase: static int leerContador(){ return contador; } static void imprimirContador(){ System.out.print("Numero de Empleados: "); // llamada al metodo: System.out.println(leerContador()); } } class Ejemplometodo { public static void main(String args[]){ Empleado jefe = new Empleado("Soto", "Martin", 341, false); // llamada al metodo (con nombre de la clase): int a = Empleado.leerContador(); Empleado.imprimirContador(); } }

Implementando Estructuras de Datos Un importante campo de aplicación de la programación es la forma de estructurar los datos, una de las estructuras más conocidas sin duda son los arrays, colas, stack, listas etc. Sin embargo existen otras más complejas, como arboles y grafos. Con Java también es muy simple de implementarlas.

Listas En teoría las listas pueden en contrario a los array aceptar muchos elementos y se pueden realizar operaciones que son más elegantes y eficientes que los arrays. Aquí se muestra un ejemplo de lista enlazada. Ingeniería en Computación, Universidad de La Seren

142

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

Ejemplo 9 class Empleado { String apellido; String nombre; int rut; boolean esFemenino; Empleado(String nn, String vn, int pn, boolean w){ apellido= nn; nombre = vn; rut = pn; esFemenino = w; } } class ListaEmpleados { Empleado elemento; ListaEmpleado continua; // Constructor para Listas con un elemento: ListaEmpleado(Empleado m){ elemento = m; continua = null; } // Constructor para Lista con más de un elemento: ListaElemento(Empleado m, ListaEmpleado l){ elemento = m; continua = l; } } class EjemploLista { public static void main(String args[]){ Empleado m1 = new Empleado("Soto", "Martin", 341, false); Empleado m2 = new Empleado("Barrios", “ Petra", 865, true); Empleado m3 = new Empleado("Meyer", "Hans", 11073, false); // Construcción de una lista con estos 3 Empleados: ListaEmpleado l = new ListaEmpleado(m1, new ListaEmpleado(m2, new ListaEmpleado(m3))); } }

Arboles En teoría los árboles no son nada más que grafos sin ciclos, cuyos elementos relevantes son los vértices(nodos) y los lados(edges). Aquí se muestra un ejemplo de árbol de jerarquerización. Este es un caso particular para la implementación de cualquier tipo de árboles, en particular arboles binarios. Ejemplo 10 class Persona { String apellido, nombre; Persona padre, madre; Persona(String apellido, String nombre, Persona padre, Persona madre){ this.apellido = apellido; this.nombre = nombre; this.padre = padre; this.madre = madre; Ingeniería en Computación, Universidad de La Seren

143

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

} void salida(int e){ for(int s = e ; s > 0 ; s--) System.out.print(' '); System.out.println(vorname + " " + nachname); if( padre != null) padre.salida(e+4); if(madre != null) madre.salida(e+4); } } class Arbolito { public static void main(String args[]){ Persona p = new Persona("Martin", "Schmidt", new Persona("Hans", "Schmidt", // padre new Persona("Ulrich", "Schmidt", null, null), // padre del padre new Person("Susanne","Schmidt", null, null)), // Madre del padre. new Person("Petra","Schmidt", // Madre new Person("Josef", "Mayer" , null, null ), // Padre de la madre. new Person("Claudia","Mayer" , null, null))); // Madre de la madre. p.salida(0); } }

Arboles AVL Métodos de Consulta Al igual que como se hizo para los árboles de búsqueda binaria podemos realizar consultas en un árbol AVL. A saber, Insertar y Eliminar, y otros métodos que no resultan tan directos como en los árboles de búsqueda binaria, por el problema de balanceo que se genera. Ejemplos: Dado el siguiente árbol T de búsqueda binaria 8

4

2

10

6

1) En este árbol, son insertados los nodos con claves 9 y 11. Generándose el árbol T1 : 8

4

2

10

6

Ingeniería en Computación, Universidad de La Seren

9

11 144

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

2) Basado en T, son insertados los nodos con claves 1, 3, 5 y 7. Generándose el árbol T2: 8

4

2

-1

-2

10

6

1

Ya al insertar la clave „1“ el árbol pierde la propiedad de AVL.. De aquí el aplicar una doble rotación. 4

2

8

1

6

10

Arbol obtenido luego de insertar las claves 3, 5 y 7. 4

2

1

8

3

6

5

10

7

La inserción de las claves „3“, „5“ y „7“ no hacen perder la propiedad AVL. La propiedad de AVL se pierde si H = +2 resp. -2. Esto se remedia mediante rotaciones. Rotaciones a) Los árboles siguientes contienen los mismos elementos y son ambos árboles de búsqueda binaria. Primero, en ambos casos k1 < k2, segundo, todos los elementos en los subárboles X son menores que k1 en ambos árboles, tercero, todos los elementos en el subárbol Z son mayores que k2. Finalmente todos los elementos en el subárbol Y están entre k1 y k2. La Ingeniería en Computación, Universidad de La Seren

145

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

conversión de uno de ellos al otro se conoce como „Rotación simple“, que significa en lo substancial cambiar la estructura del árbol. Las figuras muestran también las variantes simetricas. k2

k1

k1

k2 Z

Y

X

Y

Z

X

k1

k2

k2

k1

X

Y

X

Y

Z

Z Rotaciones Simples

Representación en Java Un árbol AVL se representa de la misma manera que un árbol binario de búsqueda, esto es con nodos que contienen punteros a su padre y a sus hijos izquierdo y derecho, sin embargo, un nodo ahora debe almacenar un campo adicional que indica la altura o balance del nodo. // Descripción de un nodo para un árbol AVL class Nodo_Avl { // Instancias protected Nodo_Avl izq; // hijo Izquierdo protected Nodo_Avl der; // hijo derecho protected int altura; // altura public Comparable datos; // elementos // Constructores public Nodo_Avl(Comparable datElem) { this(datElem, null, null ); } public Nodo_Avl( Comparable datElem, Nodo_Avl ib, Nodo_Avl db ) Ingeniería en Computación, Universidad de La Seren

146

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

{ datos = datElem; izq = ib; der = db; balance = 0; } } /* Este método puede ser llamado solamente si k2 tiene un hijo izquierdo, realizando una rotación entre el nodo k2, tal como lo muestra la figura 7. Además, actualiza la altura, asignando la nueva raíz a k2. */ private static Nodo_Avl RotacionSimpleIzq(Nodo_Avl k2) { Nodo_Avl k1 = k2.izq; k2.izq = k1.der; k1.der = k2; k2.altura = max( altura( k2.izq ), altura( k2.der ) ) + 1; k1.altura = max( altura( k1.izq ), k2.altura ) + 1; return k1; }

b) Existen situaciones en donde el desbalanceo es generado por un nodo que es insertado en el árbol que está contenido en el subárbol de el medio( es decir Y) y que al mismo tiempo como los otros arboles tienen idéntica altura. El caso es fácil de chequear y la solución es llamada “Rotación Doble”, la cual es muy similar a la rotación simple salvo que ahora se ven involucrados 4 subárboles en vez de 3. k3

k2

k1

k1

k3

D k2 B A

A B

C D

C Rotación Izq-Der, Rotación Doble.

Ingeniería en Computación, Universidad de La Seren

147

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

K3

k2

K1 A

k3

k1

k2 D

B A

B

C D

C

Rotación Der-Izq, Rotación Doble.

/* Rotación Doble, basada en Fig. 8: Este método solo puede ser usadosi k3 tiene hijo izquierdo y los hijos de k3 tienen hijo derecho. Esta rotación se conoce como rotación izq-der. Actualiza la altura, y su raíz. */ private static Nodo_Avl DobleRotacionIzq_Der(Nodo_Avl k3) { /* Rotación entre k1 y k2*/ k3.izq = RotationSimpleIzq( k3.izq); return RotationSimpleDer( k3 ); }

Ingeniería en Computación, Universidad de La Seren

148

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

Ejemplo:

Ud. podrá verificar que cualquier desbalanceo causado por una inserción en un árbol AVL puede ser realizada por una Rotación Doble o Simple, (Ver (1)). Ahora, respecto a la eficiencia de esta TDA mencionemos que almacenar la información de la altura, que en este caso son suficientes con +1, 0 y –1, es de gran utilidad Ingeniería en Computación, Universidad de La Seren

149

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

/* Método para calcular la altura de un nodo en un árbol AVL. */ private static int altura( Nodo_Avl b) { return b == null ? -1 : b.altura; }

Entonces recordemos que para Insertar un nodo con la clave „x“ en un árbol AVL, el valor „x“ se inserta recursivamente en el subarbol correspondiente, tal como en los árboles de búsqueda binario. En el caso que la altura del subárbol no cambie, la inserción concluye. En caso contrario es necesario utilizar según sea el caso, Rotación Simple o Rotación Doble. Implementación de la Inserción en los árboles AVL Archivo Nodo_Avl.java // Declaracion de la clase Nodos para los elementos en los arboles AVL. class Nodo_Avl { // Instancias protected Nodo_Avl izq; protected Nodo_Avl der; protected int altura; public Comparable datos;

// // // //

hijo izquierdo hijo derecho altura los datos como elementos del arbol avl

// Constructores public Nodo_Avl(Comparable datElem) { this(datElem, null, null ); } public Nodo_Avl( Comparable datElem, Nodo_Avl ib, Nodo_Avl db ) { datos = datElem; izq = ib; der = db; altura = 0; } } Archivo Arbol_Avl.java // // // // // // // // // // // // //

Métodos Típicos para los Arboles de Busqueda Binaria Constructor: Inicializar la raíz con null *** algunos métodos usuales para los arboles*** void insertar( x ) --> inserta x void eliminar( x ) --> elimina x Comparable hallar( x ) --> hallar un Elemento que corresponde a x Comparable hallarMin( ) --> Entrega el Elemento más pequeño Comparable hallarMax( ) --> Entrega el Elemento más grande boolean esVacio( ) --> Return true si es vacio; else false void hacerVacio( ) --> Eliminar todos void printArbol( ) --> Salida de los datos en una sucesión ordenada void salidaArbolBinario() --> Salida de los datos girados en 90 grados.

/* Ingeniería en Computación, Universidad de La Seren

150

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

* Comparaciones se basan en el método compareTo.(REPASAR) */ public class Arbol_Avl { /* Raiz del Arbol */ private Nodo_Avl raiz; /* * Constructor por defecto */ public Arbol_Avl( ) { raiz = null; } /* * Insertar: Duplicados son ignorados. * x es el dato a ser insertado. */ public void insertar(Comparable x ) { raiz = insertar( x, raiz ); } /* * Eliminar un nodo del Arbol. Caso que x no este, * nada ocurre. * Si x esta, es eliminado. */ //no esta la implementación...... /* * Determinar el elemento más pequeño en el arbol.. * Devuelve: el dato más pequeño o null, * en el caso que el arbol este vacio. * Analogamente se podría determinar el más grande elemento en el */ //no esta implementado.....

arbol

/* * Eliminar el arbol. */ //no esta implementado.... /* * Test, si el arbol esta vacio o no. * devuelve true, caso de vacio; sino false. */ public boolean esVacio( ) { return raiz == null; } /* * Entregar el contenido del árbol en una sucesion ordenada. */ public void printArbol( ) { if( esVacio( ) ) System.out.println( "Arbol vacio" ); else printArbol( raiz ); } /* * Salida de los elementos del arbol binario rotados en 90 grados */ Ingeniería en Computación, Universidad de La Seren

151

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

public void salidaArbolBinario() { if( esVacio() ) System.out.println( "Arbol vacio" ); else salidaArbolBinario(raiz,0); } /* * Metodo interno para tomar un nodo del arbol. * Parametro b referencia al nodo del arbol. * Devuelve los elementos o null, * caso de b sea null. */ private Comparable elementAt(Nodo_Avl b ) { return b == null ? null : b.datos; } /* * Metodo Interno para agregar o insertar un nodo en un subarbol. * x es el elemento a agregar. * b es el correspondiente nodo raiz. * Devuelve la nueva raiz del respectivo subarbol. */ private Nodo_Avl insertar(Comparable x, Nodo_Avl b) { if( b == null ) b = new Nodo_Avl(x, null, null); else if (x.compareTo( b.datos) < 0 ) { b.izq = insertar(x, b.izq ); if (altura( b.izq ) - altura( b.der ) == 2 ) if (x.compareTo( b.izq.datos ) < 0 ) b = RotacionSimpleIzq(b); else b = RotacionDobleIzq_Der(b); } else if (x.compareTo( b.datos ) > 0 ) { b.der = insertar(x, b.der); if( altura(b.der) - altura(b.izq) == 2) if( x.compareTo(b.der.datos) > 0 ) b = RotacionSimpleDer(b); else b = RotacionDobleDer_Izq(b); } else ; // Duplicados; no hace nada b.altura = max( altura( b.izq ), altura( b.der ) ) + 1; return b; } /* * Metodo Interno para determinar el dato más pequeño. * b es la raiz. * Devuelve: Nodo con el elemento mas pequeño. */ private Nodo_Avl hallarMin(Nodo_Avl b) { if (b == null) return b; while(b.izq != null ) b = b.izq; Ingeniería en Computación, Universidad de La Seren

152

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

return b; } /* * Analogamente al anterior pero el más grande. */ private Nodo_Avl hallarMax(Nodo_Avl b ) { if (b == null) return b; while (b.der != null) b = b.der; return b; } /* * Metodo interno para determinar un dato. * x es el dato buscado * b es la raiz * Devuelve: Nodo con el correspondiente dato. */ private Nodo_Avl hallar(Comparable x, Nodo_Avl b) { while( b != null ) if (x.compareTo( b.datos) < 0 ) b = b.izq; else if( x.compareTo( b.datos ) > 0 ) b = b.der; else return b; // paso return null; // no paso nada } /* * Metodo Interno para devolver los datos de un subarbol en una sucesion ordenada. * b es la raiz. */ private void printArbol(Nodo_Avl b) { if( b != null ) { printArbol( b.izq ); System.out.println( b.datos ); printArbol( b.der ); } } /* * salida del arbol binario rotado en 90 Grados */ private void salidaArbolBinario(Nodo_Avl b, int nivel) { if (b != null) { salidaArbolBinario(b.izq, nivel + 1); for (int i = 0; i < nivel; i++) { System.out.print(' '); } System.out.println(b.datos); salidaArbolBinario(b.der, nivel + 1); Ingeniería en Computación, Universidad de La Seren

153

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

} } /* * Salida: altura de los nodos, o -1, en el caso null. */ private static int altura(Nodo_Avl b) { return b == null ? -1 : b.altura; } /* * Salida: Maximum entre lhs y rhs. */ private static int max( int lhs, int rhs ) { return lhs > rhs ? lhs : rhs; } /* * Rotacion Simple Izquierda(simetrica a Rotacion Simple Derecha). * Para los arboles AVL, esta es una de las simples rotaciones. * Actualiza la altura, devuelve la nueva raiz. */ private static Nodo_Avl RotacionSimpleIzq(Nodo_Avl k2) { Nodo_Avl k1 = k2.izq; k2.izq = k1.der; k1.der = k2; k2.altura = max( altura( k2.izq ), altura( k2.der ) ) + 1; k1.altura = max( altura( k1.izq ), k2.altura ) + 1; return k1; } /* * Rotación Simple Derecha. */ private static Nodo_Avl RotacionSimpleDer(Nodo_Avl k1) { Nodo_Avl k2 = k1.der; k1.der = k2.izq; k2.izq = k1; k1.altura = max( altura( k1.izq ), altura( k1.der ) ) + 1; k2.altura = max( altura( k2.der ), k1.altura ) + 1; return k2; } /* * Rotacion doble: primero hijo izquierdo con su hijo derecho * entonces nodo k3 con el nuevo hijo izquierdo. * para los arboles AVL, esta es una doble rotación * actualiza alturas, entrega nueva raiz. */ private static Nodo_Avl RotacionDobleIzq_Der(Nodo_Avl k3) { k3.izq = RotacionSimpleDer( k3.izq ); return RotacionSimpleIzq( k3 ); } /* * rotacion doble: primero hijo derecho * con su hijo izquierdo; luego nodo k1 con nuevo hijo derecho. * Para los AVL, esta es una doble rotación. * actualiza alturas, entrega nueva raiz. */ private static Nodo_Avl RotacionDobleDer_Izq(Nodo_Avl k1) { k1.der = RotacionSimpleIzq(k1.der); Ingeniería en Computación, Universidad de La Seren

154

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

return RotacionSimpleDer(k1); } } archivo Arbol_AvlTest.java public class Arbol_AvlTest { // Programa Test public static void main(String [] args) { Arbol_Avl b1 = new Arbol_Avl(); Arbol_Avl b2 = new Arbol_Avl(); for (int i = 0; i < 7; i++) // { Integer r = new Integer(i); b1.insertar(r); } System.out.println("Arbol girado en 90 grados"); b1.salidaArbolBinario(); for (int i = 0; i < 10; i++) { // Genera un número entre 0 y 100 Integer r = new Integer((int)(Math.random()*100)); b2.insertar(r); } System.out.println("Arbol girado en 90 grados"); b2.salidaArbolBinario(); System.out.println("Travesia en Inorden(Izq-Raiz-Der)"); b2.printArbol(); } } Salida que se genera: Arbol girado en 90 grados 0 1 2 3 4 5 6 Arbol girado en 90 grados 4 14 35 39 52 64 74 75 77 Travesia en Inorden(Izq-Raiz-Der) 4 14 35 39 Ingeniería en Computación, Universidad de La Seren

155

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

52 64 74 75 77

Interpretación de la salida Arbol girado en 90 grados 0 1 2 3 4 5 6

La implementación de los árboles AVL, así como su salida están basados en los ejemplos y materiales entregados en (3). 3

1

0

5

2

4

6

Propuestas: Una mejora factible de considerar en la implementación del método insertar es considerar que los elementos a ingresar son String o caracteres, además de considerar el factor de balance y la nueva raíz que se obtiene. Como se muestra en el ejemplo siguiente. caracter que desea insertar al arbol-AVL (Borrar: \n): a a insertado AVL con balanceo: a(0)

Caracter que desea insertar al arbol-AVL (Borrar: \n): b b insertado AVL con balanceo: b(0) a(1)

c insertado AVL con balanceo: c(0) b(0) a(0)

Ingeniería en Computación, Universidad de La Seren

156

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

Jerarquia de Clases Las clases que poseen la (o las) propiedad de la clase superior son descritas como subclases de la superclase. Ejemplo 11 class Alumno { String apellido; String nombre; boolean esFemenino; String carrera; byte semestre; // Constructor Alumno (String apellido, String nombre, boolean,esFemenino, String carrera, byte semestre) { this.apellido = apellido; this.nombre = nombre; this.esFemenino = esFemenino; this.carrera = carrera; this.semestre = semestre; } }

Una clase puede a menudo ser especializada, de la misma manera que una superclase puede ser generalizada. Un ejemplo, para la especialización sería una clase Colaborador, la que asume una nueva propiedad traducida en una variable tarifa, incorporandosela a la clase Empleado. Ejemplo 12 class Colaborador { String apellido; // copia de la clase Empleado String nombre; // copia de la clase Empleado int rut; // copia de la clase Empleado boolean esFemenino; // copia de la clase Empleado String tarifa;// trato preferencial?? // Constructor Colaborador (String apellido, String nombre, int rut, boolean esFemenino,String tarifa) { this.apellido = apellido; this.nombre = nombre; this.rut = rut; this.esFemenino = esFemenino; this.tarifa = tarifa; }

}

Importante: La clase Persona es también una superclase de la clase Colaborador, pero ella no es una superclase directa. En contrario, la clase Colaborador es una subclase ( o indirecta) subclase de la clase Persona. En general, entre una super y una subclase pueden existir muchas (sub- resp.super-)clases.

Ingeniería en Computación, Universidad de La Seren

157

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

Herencia En Java la herencia es descrita a través de la palabra reservada extends, en general se tiene class sub-clase extends super-clase{...}

La Herencia es una de las características más importantes de la POO. En su forma más simple, es el proceso de construir sobre una clase que ya está definida, extendiéndola de alguna forma. Cuando entiende cómo funciona la herencia, puede diseñar y derivar nuevas clases diferentes en forma sustancial a las clases existentes. La herencia proporciona acceso a la información contenida en cualquiera de las clases madre a lo largo de la cadena de herencia. Todas las clases que se escriben, excepto el caso especial de las interfaces, son de forma automática subclases de la clase raíz que incluye Java, llamada Object (objeto). Al crear una clase ya está usando la herencia, es así como este concepto permite a las subclases aprovechar las características de las clases que proporciona Java, las de otros programadores, proveedores y las creadas por el programador. La mejor forma de visualizar la herencia es pensar en un árbol jerárquico. La siguiente figura muestra una jerarquía de clase básica, donde las clases inferiores se derivan de las superiores. Una subclase hereda todos los métodos y variables de todas sus clases madre. Al escribir una subclase derivada, es como si tecleara de nuevo todos los métodos y variables públicas existentes en las superclases. Desde luego, Java hace esto de forma automática, lo único que debe hacer es crear los métodos y variables nuevos o diferentes que requiere la nueva subclase y que sus clases madres no proporcionan. A diferencia de otros lenguajes orientados a objetos, como C++, Java sólo permite derivar a partir de una clase madre. No se puede derivar una nueva subclase a partir de dos o más clases madre. La herencia múltiple es el proceso de derivar una clase a partir de dos o más superclases –y es una de las características que los diseñadores de Java dejaron fuera. Afortunadamente, como veremos en el siguiente tip, Java proporciona una alternativa mucho más transparente que la herencia múltiple, utilizando lo que Java llama interface. En la figura se muestra en flecha punteada el modelo de herencia múltiple, en el sentido que Juan no puede heredar de Gerente e Ingeniero. Empleado

Ingeniero

Gerente

Juan

Ingeniería en Computación, Universidad de La Seren

Secretaria

Susana

158

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

Ejemplo 13 // Empleado como subclase de Persona class Empleado extends Persona { // componentes heredadas:directo de Persona: apellido, nombre, esFemenino. // nueva declaración de componente objeto: int rut; // constructor Empleado (String apellido, String nombre, int rut, boolean esFemenino) { this.apellido = apellido; this.nombre = nombre; this.rut = rut; this.esFemenino = esFemenino; } void salida() { System.out.print(esFemenino ? "Sra. " : "Sr. "); System.out.print(nombre + " " + apellido); System.out.println(" (Rut: " + rut + ")"); } } // Alumno como subclase de Persona class Alumno extends Persona { // componente heredada: // directamente de Persona: apellido, nombre, esFemenino // nueva declaración de componentes objeto: String carrera; byte semestre; // Constructor Alumno (String apellido, String nombre, boolean esFemenino, String carrera, byte semestre) { this.apellido = apellido; this.nombre = nombre; this.esFemenino = esFemenino; this.carrera = carrera; this.semestre = semestre; } } //Colaborador como subclase de Empleado class Colaborador extends Empleado { // componentes heredadas: // indirectamente de Persona: apellido, nombre, esFemenino // directamente de Empleado: rut, salida() // nueva componente Objeto: String tarifa; // constructor Colaborador (String apellido, String nombre,int rut, boolean esFemenino, String tarifa) { this.apellido = apellido; this.nombre = nombre; this.rut = rut; this.esFemenino = esFemenino; this.tarifa = tarifa; } }

Ingeniería en Computación, Universidad de La Seren

159

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

Estos segmentos de programa se pueden visualizar a través de la siguiente figura dejando en claro el concepto de herencia o jerarquía. Persona Apellido : String Nombre: String esFemen: boolean

Empleado Rut : int Salida (·)

alumno carrera: String Semestre: byte

Colaborador Tarifa: String

Las variables instanciadas apellido, nombre y esFemenino están implícitamente declaradas en la subclase a través de la herencia. Ud. pueden notar que para colaboradores que realizan labor de investigación pueden de manera elegante a través de 2 superclases ser modeladas, a saber Colaborador y Academico. De esta forma pueden varias clases tener sus propiedades en una o varias superclases, en tal caso se habla de Herencia Multiple. Java no permite (en contrario a C++) la herencia multiple, en la práctica significa que tras la llave extends puede ser incluida solamente una superclase. Jerarquia de clases en Java La clase Object pertenece a una de las clases estandares de Java, se encuentra en java.lang.Object, en términos generales se dice que la clase Object se encuentra en la raiz de la jerarquía de clases. class Persona { ... } //posee el mismo significado que class Persona extends Object { ... }

Ingeniería en Computación, Universidad de La Seren

160

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

Herencia y Constructores class Alumno extends Persona { String carrera; byte semestre; // constructor general: Alumno(String apellido, String nombre, boolean esFemenino,String carrera, byte semestre) { // llamada a los constructores de "Persona" con "super": super(apellido, nombre, esFemenino); this.carrera = carrera; this.semestre = semestre; } // Constructor para alumno de Computación en I Sem: Alumno (String apellido, String nombre, boolean esFemenino) { // llamada del constructor de "Alumno" con "this": this(apellido, nombre, esFemenino, "Computacion", 1); } }

Como ejemplo del uso de estas propiedades sería contar el número de todos los Empleados. Para eso la clase Empleado debería verse así. Ejemplo 14 class Empleado extends Persona{ static int numEmpleados = 0; int rut; // cambio del constructor Empleado () { numEmpleados++; } // constructor Empleado (String apellido, String nombre, int rut, boolean esFemenino) { super(apellido, nombre, esFemenino); numEmpleados++; this.rut = rut; } void salida() { System.out.print(esFemenino ? "Sra " : "Sr "); System.out.print(nombre + " " + apellido); System.out.println(" (Rut: " + rut + ")"); } }

Es generada una instancia de la subclase Empleado, la que es declarada en la clase Empleado, de manera que el valor de numEmpleados entrega un objeto Empleado. La ausencia de parametros en el constructor Empleado permite que el número de instancias de las subclases sean llamadas.

Ingeniería en Computación, Universidad de La Seren

161

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

Dynamic Binding Dynamic Binding es una característica común de los lenguajes orientados a objeto y se refiere al proceso de entrelazar un programa de forma que existan todas las conexiones apropiadas entre sus componentes, en rigor es una consecuencia de la puesta en práctica o realización del polimorfismo. Polimorfismo Polimorfismo es un término que se utiliza para describir una situación en donde un nombre puede referirse a diferentes métodos. En Java existen dos tipos de polimorfismo: el que ocurre en la sobrecarga y el que ocurre en el reemplazo. El polimorfismo en la sobrecarga sucede cuando existen varios métodos dentro de una clase, todos ellos con el mismo nombre, lo cual está permitido siempre y cuando los métodos tengan diferente número o tipos de parámetros. Tener diferentes tipos de retorno no sirve al eliminar la ambigüedad de los métodos y no ayuda si se necesitan dos métodos con el mismo nombre y los mismos parámetros pero diferentes tipos de retorno. Al crear métodos de clase polimórficos y escribir código que acceda a ellos, Java determina cuál de los métodos debe llamar durante la compilación. Por otra parte, al reemplazar métodos, Java determina cuál debe llamar al momento de ejecutar el programa, no durante la compilación. Para determinar qué métodos debe llamar, Java debe considerar no sólo los que están dentro de una clase, sino además los que están en las clases madres. El reemplazo ocurre cuando un método en una clase tiene el mismo nombre y firma (número, tipo y orden de los parámetros) que un método de una clase madre ( o superclase). En caso de que los métodos tengan el mismo nombre y firma, el método de la clase derivada siempre reemplaza al método de la clase madre. Ejemplo 15 class EjemploPoli { public static void pago (Empleado empleado) { System.out.println("Empleado" + empleado.apellido + " recibe Pago."); } public static void main (String[] args) { Empleado empleado; // Polimorfismo empleado = new Colaborador("Meyer", "Hans", false, 1, "IIa"); // Polimorfismo en la entrega de parametros pago(empleado); } }

Ingeniería en Computación, Universidad de La Seren

162

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

Sobreescritura de métodos Ejemplo 16 class Colaborador extends Empleado { String tarifa; // sobreescritura de Metodo void salida () { System.out.print(esFemenino ? "Sra. " : "Sr "); System.out.print(nombre + " " + apellido); System.out.println(" Rut: " + rut); System.out.println(" Tarifa: " + tarifa); } } class EjemploSobreescritura { public static void main (String[] args) { Empleado m; m = new Empleado("Meyer", "Hans", false, 1); m.salida(); // llamada a salida() de la clase "Empleado" m = new Colaborador("Soto", "Martin", false, 2, "IIa"); m.salida(); // llamada a salida() de la clase "Colaborador" } }

Clases Abstractas y Métodos Abstractos Al diseñar un programa en Java o cualquier otro lenguaje orientado a objetos, por lo general se inicia con una descripción de alto nivel de lo que se desea que haga el programa. Los lenguajes orientados a objetos facilitan el modelaje (o la representación) del problema que tiene que resolver el programa, ya que se pueden utilizar clases para representar las “cosas” que componen la solución. Digamos que quiere comenzar con el modelaje de un Alumno y un Empleado y que crea clases para cada uno de estos modelos. Al desarrollarlas, quizá aparecerán características que son comunes a los Alumnos y a los Empleados. Por ejemplo, ambos hacen docencia en la Uni, entonces será necesario escribir un método (tal vez llamado docente) para cada uno. Java proporciona un tipo especial de clase, llamada clase abstracta, que puede ayudar a la organización de las clases basadas en métodos comunes. Una clase abstracta permite colocar los nombres de los métodos comunes en una sola clase (sin tener que escribir el código que los instrumente). Después, al crear nuevas clases como Alumno y Empleado, éstas pueden derivar de una clase abstracta que contiene una serie de métodos requeridos (docente, por decir algo). Los métodos abstractos contienen sólo el nombre del método seguido de una lista de parámetros (esto también se conoce como firma). No contienen el código que instrumenta el método –esto se deja para las clases derivadas-, después. Otros puntos clave acerca de los métodos abstractos son:  

Las clases que contienen métodos abstractos se conocen como clases abstractas. Un programa no puede crear instancias de una clase abstracta de forma directa, es necesario crear instancias de sus subclases.

Ingeniería en Computación, Universidad de La Seren

163

Dr. Eric Jeltsch F.

 

Capítulo 6: Programación Orientada a Objetos

Las clases abstractas pueden contener una mezcla de métodos abstractos y no abstractos (concretos). Los métodos concretos contienen la instrumentación del método. Cualquier subclase que extienda a la clase abstracta debe proporcionar la instrumentación de todos los métodos abstractos. En caso contrario, la subclase misma se convierte en una clase abstracta.

Un ejemplo de método abstracto puede ser integrado en la clase Persona, con el nombre de método Ocupación(), la que para esta clase no es todavía realizada y por tal motivo se deja declarada como abstracta. Ejemplo 17 abstract class Persona { String apellido; String nombre; boolean esFemenino; Persona () { } // constructor Persona (String apellido, String nombre, boolean esFemenino) { this.apellido = apellido; this.nombre = nombre; this.esFemenino = esFemenino; } // método Abstracto abstract void Ocupacion(); }

Importante: Los métodos abstractos al igual como otros métodos son heredados. class Empleado extends Persona { int rut; Empleado (String apellido, String nombre, int rut, boolean esFemenino) { super(apellido, nombre, esFemenino); this.rut = rut; } void salida() { System.out.print(esFemenino ? "Sra " : "Sr "); System.out.print(nombre + " " + apellido); System.out.println(" (Rut: " + rut + ")"); } // sobreeescritura del método abstracto heredado void Ocupacion() { System.out.println("Trabajan"); } } class Alumno extends Persona { String carrera; byte semestre; Student (String apellido, String nombre, boolean esFemenino, String carrera, byte semestre) { super(apellido, nombre, esFemenino); this.carrera = carrera; this.semestre = semestre; Ingeniería en Computación, Universidad de La Seren

164

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

} // sobreescritura del método abstracto heredado void Ocupacion() { System.out.println("Aprender"); } }

Interfaces En Java, una clase puede tener sólo una superclase (clase madre). Como ya vimos, puede crear nuevas clases derivándolas de clases existentes, heredando así las variables y métodos de la clase madre. Ésta es una técnica poderosa que permite agregar funcionalidad de forma creciente y al mismo tiempo mantener las clases tan sencillas como sea posible. Además, obliga a pensar bien el diseño de los programas y organizar su flujo. Sin embargo, tal vez quiera derivar características de más de una clase madre, lo cual puede venir a raíz del problema que desea resolver, como representar la solución en términos de clases. Java no permite la herencia múltiple, es decir, la capacidad de derivar una nueva clase a partir de más de una clase existente. De cualquier modo, Java tiene una forma para declarar tipos especiales de clase que permite un número ilimitado de derivaciones. Las diferencias principales entre una interface y una clase son las siguientes:       

Una interface, al igual que una clase abstracta, proporciona los nombres de los métodos pero no sus instrumentaciones. Una clase puede instrumentar varias interfaces, ordenando de esta forma la restricción de herencia múltiple de Java. Un programa no puede crear una instancia u objeto de una interface. Todos los métodos de una interface son implícitamente públicos y abstractos. Todas las variables de una interface son implícitamente públicas, estáticas y finales. No se permite ningún otro tipo. La clase que instrumenta a la interface debe instrumentar todos los métodos, a menos que sea declarada como abstracta. Una interface no tiene una clase padre antecesora (Object). En su lugar, las interface tienen una jerarquía independiente que puede ser aplicada a cualquier parte del árbol de clases.

Ejemplo 18 public class Alumno extends Persona implements nombreEntidad{ private String matriculaNo; public Alumno(String matriculaNo) { this.matriculaNo = matriculaNo; } //constructor public String getMatriculaNo() { return matriculaNo; } //getMatriculaNo; public boolean setMatriculaNo(String matriculaNo) if (matriculaNo.compareTo("")==0) Ingeniería en Computación, Universidad de La Seren

{

165

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

{ this.matriculaNo = matriculaNo; return true; } else return false; } //setMatriculaNo() public String getNombre() return nombre; } //getNombre()

{

public boolean setNombre(String newNombre) { if (newNombre.compareTo("")!=0) { nombre = newNombre; return true; } else return false; } //setNombre() public String toString() { return("Nombre:"+this.getNombre()+"\nMatricula

Numero:

"+this.getMatriculaNo()

); } //toString() public static void main(String[] args){ Alumno mario = new Alumno("0793022"); System.out.println( mario.getMatriculaNo() ); System.out.println("mario.toString()returns: \n"+mario.toString() ); mario.setNombre("Mario Jorquera"); System.out.println("mario.toString()returns: \n"+mario.toString() ); } //main() } //end class Alumno class Persona { String nombre; } //class Persona interface nombreEntidad { String getNombre(); boolean setNombre(String newNombre); } //interface nombreEntidad

Ingeniería en Computación, Universidad de La Seren

166

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

Modelamiento UML Persona nombre: String

nombreEntidad

getNombre( ) : String setNombre(String newNombre): boolean

Alumno matricNº: String getNombre: String setNombre(String newNombre): boolean getMatricNº( ) : String setMatricNº(String newMN): boolean

Una interface agrega la flexibilidad de declarar un conjunto de métodos y variables que pueden ser instrumentados por cualquier clase en el árbol de jerarquía de clases. Otro uso que tienen las interfaces es proporcionar un conjunto de constantes a las que pueda accederse de forma directa con cualquier otra clase. Por ejemplo, las siguientes instrucciones muestras cómo definir una interfaz que defina un conjunto de constantes. Importante: En contrario a la herencia normal puede una clase implementar varias Interfaces. Las interfaces al igual que las clases pueden ser utilizadas como tipo de dato. Ejemplo, dado una Interface Academico: interface Academico { byte SIN_TITULO = 0; byte MAGISTER= 1; byte DOCTOR = 2; byte PROFESOR = 3; void titulo(); }

Ahora si Ud. notan la clase Investigacion nos da una información extra sobre el curriculum del Academico dentro de la organización o Colaboradores. Es así como es posible tener: class Investigador extends Colaborador implements Academico { byte titulo; Investigador (String apellido, String nombre, int rut, boolean esFemenino, int tarifa, byte titulo) { super(apellido, nombre, rut, esFemenino, tarifa); this.titulo = titulo; } void Ocupacion() { System.out.println("Investigar"); } // Implementar el método abstracto void titulo() { switch(titulo) { case MAGISTER: 167 Ingeniería en Computación, Universidad de La Seren

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

case DOCTOR: case PROFESOR: System.out.println("Titulo o grado"); break; case SIN_TITULO: default: System.out.println("Sin Titulo"); break; } } }

Paquetes Generalmente las clases e Interfaces en Java están subordinadas a paquetes, de manera que para utilizarlos significa darles en el encabezamiento del programa la “ruta” adecuada. Para generar nuestros propios paquetes se deben declarar a través de la declaración package NombrePaquete;

Con esto, se verifica que toda clase e interface contenida en el programa pertenece a NombrePaquete. // Declaracion de NombrePaquete package AdministracióndelPersonal class Personal { String apellido; String nombre; boolean esFemenino; Personal () { } Personal (String apellido, String nombre, boolean esFemenino){ this.apellido = apellido; this.nombre = nombre; this.esFemenino = esFemenino; } }

Declaración import import NombrePaquete.Tiponombre; import NombrePaquete.*;

La primera declaración declara el paquete completo con todas sus clases e interfaces, de manera que durante la ejecución del programa el compilador deberá examinar la clase o paquete correspondiente y no todo su contenido, como se realiza en la segunda declaración // Declaracion de NombrePaquetes package AdministracióndelPersonal; // Importando la clase java.lang.Object // (Sin más ni más, siempre esta este paquete presente) import java.lang.Object; class Persona extends Object { Ingeniería en Computación, Universidad de La Seren

168

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

String apellido; String nombre; boolean esFemenino; Persona () { } Persona(String apellido, String nombre, boolean esFemenino) { this.apellido = apellido; this.nombre = nombre; this.esFemenino = esFemenino; } }

Java-Paquetes Estandar Para Java existe un gran conjunto de paquetes estandares, en donde las clases e interfaces para diferentes aplicaciones están a disposición.             

java.lang: clases e interfaces fundamentales. java.io: Entrada y Salida de datos y filtros. java.net: soporte para redes (Sockets, URLs, ...) java.util: clases para diversas estructuras de datos, entre ellas, Listas, Stacks, Hash, fecha y hora. java.util.zip (desde Java 1.1): compresión de datos. java.text (desde Java 1.1): soporte para programas, que consideran diversas lenguajes y países (por ejemplo: formato de salida para números, fecha u hora local). java.math: soporte para el manejo de números, exactitud, etc. java.beans (desde Java 1.1): soporta los llamados beans (en Java son componentes de software que pueden ser reutilizados.) java.applet: clase que ayuda en la generación de Applets (programas Java, que se ejecutan bajo un determinado Browser como parte de una página WWW). java.awt: popularmente llamada Abstract Windowing Toolkit (abrev. AWT), una colección de clases e interfaces para las interfaces gráficas. java.awt.event (desde Java 1.1): una extensión de AWT. java.awt.image: Elaboración de imágenes. java.awt.peer: interfaces, que son significativas en la realización de AWT .

Programación Orientada a Objetos comparada con la Programación de Procesos y programación orientada a eventos. Al comparar la programación orientada a objetos (POO) con la metodología tradicional de programación por proceso, puede ver que la primera proporciona un nuevo marco de referencia a través del cual se pueden estudiar los problemas de programación. En una metodología por proceso, se escriben funciones para resolver piezas de un problema. Si otro programador ha escrito funciones que resuelven problemas específicos, es posible, en un nuevo programa, utilizar (llamar) estas funciones. En la programación tradicional, el programador comúnmente ocupa más tiempo en las funciones que en el problema que debe resolver el programa. Como ya hemos visto, la programación orientada a objetos proporciona una forma de ver los programas en función de los datos y los métodos que operan sobre ellos.. En la programación Ingeniería en Computación, Universidad de La Seren

169

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

orientada a objetos, la atención se aleja de las funciones y se acerca a las cosas (objetos) que componen el programa. Las diferencias básicas entre la programación orientada a objetos y el enfoque de procesos pueden agruparse en cuatro principios básicos: abstracción, encapsulado, herencia y polimorfismo. La abstracción es el proceso de ignorar temporalmente los detalles subyacentes al objeto, para centrar la atención en el problema u objeto y así extraer sus características esenciales. Por ejemplo, si se consideran los neumáticos de un auto, el neumático abstracto puede tener una marca, tamaño precio y una cantidad ideal de aire. Estas características se aplican a todos los neumáticos. Al utilizar la abstracción es posible centrar la atención sobre estas características cave (comunes), en lugar de hacerlo sobre los detalles de un tipo específico de neumático. Encapsular es el proceso de agrupar la información abstraída del objeto con las operaciones (métodos) que un programa puede realizar sobre los datos. Por ejemplo, una clase es el encapsulado de los datos y métodos de un objeto. La herencia es un marco en el cual se pueden crear clases nuevas al introducir nuevas características o cambios a clases existentes. La herencia libera al programador de la tarea de rescribir funciones cuando se deben hacer pequeños cambios. Finalmente, el polimorfismo es la habilidad que tiene un objeto de tomar diferentes formas. El prefijo poli significa “muchas”; morfismo “formas”. Por ejemplo, en un programa, un objeto polimorfo que represente un teléfono puede cambiar de forma para representar un teléfono de tonos, un teléfono de pulsos o incluso un teléfono celular. Como puede notar algunos conceptos de la POO son análogos a los métodos de programación convencional, por ejemplo. Un método es como un procedimiento porque ambos contienen instrucciones de procesamiento. Las variables de clase y modelo se correlacionan a los datos de la programación tradicional. Los métodos y datos son diferentes porque los procedimientos no están encapsulados normalmente con los datos que manipulan. Una clase es como un tipo abstracto de datos, aunque para la POO, el proceso de escribir no se revela fuera de la clase. La herencia no tiene analogía inmediata en la programación convencional. El paso de mensajes reemplaza a las llamadas de función como método principal de control en los sistemas orientados a objeto. Con las llamadas de funciones, los valores se presentan y el control regresa a la función que efectúa la llamada. Por el contrario, los objetos entran en acción gracias a los mensajes, y el control está distribuido. En resumen, la orientación a objetos se define por medio de un conjunto de mecanismos: objetos, clases y modelos, métodos y mensajes, y herencia. Estos mecanismos dan origen a conceptos clave inherentes a los sistemas orientados a objetos: encapsulación, abstracción y polimorfismo. Los mecanismos y conceptos de la orientación a objetos llevan esencialmente a Ingeniería en Computación, Universidad de La Seren

170

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

los programadores a escribir código en un nivel superior de abstracción. Asimilar las ideas orientadas a objetos significa aprender las diferencias así como las similitudes entre este método y la programación convencional.

Un ejemplo practico. Metas: a) Recrear los conceptos de la POO, vistos hasta ahora. b) Ganar habilidades en la creación y uso de una jerarquía de clases.

Descripción del Problema Crear un sistema capaz de administrar un examen tipo cuestionario, basado en 3 tipos de preguntas. Se fijan entre ellas, preguntas del tipo a) Verdadero/falso, b) Selección múltiple, c) Respuesta cortas. Cada pregunta debe tener un puntaje o peso, el que representará el resultado del examen. Su propuesta deberá ser capaz de crear un pequeño examen, con tal vez 10 preguntas, y administrarlo en el sentido de dar respuestas a las distintas preguntas que se proponen pero en el contexto de la pregunta, ya sea del tipo a) , b) o c). Para finalmente reportar los resultados en porcentaje.

Algunas consideraciones para la propuesta de solución. Pregunta.java: es una clase abstract que acoge los elementos comunes a todos los tipos de preguntas. Debería contener:   

una variable peso para el "peso" de la pregunta, además de métodos public getPeso() y setPeso() para esta variable. una variable text para el texto de la pregunta, además de un método public getText() para esta variable. El texto de la pregunta deberá ser "seteado" por constructores y nunca cambiado, de manera que Ud. no necesita un método set para ello. un método abstract buscar(), que pedirá la pregunta, lee la respuesta del usuario y return un resultado boolean indicando si el usuario la respondió correctamente. También deberá imprimir un mensaje al usuario, llamando la atención de que el resultado a la pregunta fue correcto o no. Estudie la forma de definir las variables, es decir protected, private, u otra.

Ingeniería en Computación, Universidad de La Seren

171

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

/** * Una clase que representa una pregunta de un examen. * */ public abstract class Pregunta { /** * El nº de puntos para las preguntas. Default es un punto. * es private en vez de protected , así la subclase son forzadas a usar * el metodo getPeso, y así prevenir pesos ilegales. */ private int peso = 1; /** * texto de la pregunta. Todas las preguntas tienen un texto; la diferencia * esta en el tipo de respuesta y el método de chequear la respuesta. */ protected String text; /** * Obtener el texto de esta pregunta. * * @return el texto de esta pregunta */ public String getText() { return text; } // end getText /** * obtener el peso de esta pregunta * * @return el peso */ public int getPeso() { return peso; } // end getPeso /** * setear el peso de esta pregunta * * @param wt el nuevo peso para esta pregunta. Debe ser mayor que cero, o el metodo imprime un * un mensaje de error y se sale el programa. */ public void setPeso(int wt) { if (wt = eleArray.length) { System.out.println("Error: respuesta para selección multiple deben ser un index legal en el array de elección"); System.exit(1); } // end if text = pregunta; correctResp = respuesta; elec = eleArray; setPeso(wt); } // end constructor /** * Busca el usuario la pregunta y chequea para ver si la respuesta dada es correcta. * El usuario debe responder 'a', 'b', 'c', o 'd'. Si el usuario ingresa una respuesta, que no esta * este metodo le mandara un mensaje y lo intenta otra vez, hasta obtener la respuesta legal. * Cuando el usuario ingresa una respuesta valida prints un message estableciendo que la respuesta es correcta. * * @return true si el usuario responde correctamente */ public boolean buscar() { int numElec = elec.length; // nº de elecciones para esta pregunta Ingeniería en Computación, Universidad de La Seren

176

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

System.out.println(text + "?"); for (int i = 0; i < numElec; i++) { System.out.println(" " + (char)('a' + i) + ". " + elec[i]); } // end for System.out.print("ingrese la letra de su eleccion: "); // obtener la respuesta del usuario y la traslada a mayuscula String usuText = SavitchIn.readLine().toLowerCase(); if (usuText.length() != 1) { System.out.println("Error: por favor ingrese un caracter simple"); return buscar(); // repetir } // end if // el usuario responde como un numero, con 'a' = 0, 'b' = 1, etc. int respIndex = usuText.charAt(0) - 'a'; if (respIndex < 0 || respIndex >= numElec) { System.out.println("Error: caracter ilegal"); return buscar(); // repetir } // end if if (respIndex == correctResp) { System.out.println("correcta!"); return true; } else { System.out.println("no, la respuesta es " + elec[correctResp]); return false; } // end if } // end buscar } // end class Selec_Mul_Pregunta

Exam.java: Es una clase que entrega una colección de preguntas para un examen dado. El examen parte vacío (no existen preguntas), y proporciona un método para agregar preguntas a un examen. Esta clase deberá contener: 

Un array de preguntas. Estudie la forma de limitar el nº límite de preguntas, por ahora cree un array de tamaño 10.



Un contador para el nº de preguntas en el array.



Un método agregaPregunta() , el que toma una pregunta (de cualquier tipo) como argumento y la agrega al examen.



Un método darExam() el cual administra el examen al usuario, con el fin de garantizar el nº de respuestas, con su porcentaje y el redondeo apropiado, como resultado. /** * Un examen es una coleccion de preguntas. En este caso, un examen esta * implementado como un array de preguntas y tiene un tamaño maximo. */ public class Exam { /** * El nº maximo de preguntas admitidas en un examen. */

Ingeniería en Computación, Universidad de La Seren

177

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

public static final int MAX_PREGUNTAS = 10; /** * El nº actual de preguntas actualmente en el examen. */ private int numPreguntas = 0; /** * Las preguntas en el examen. */ private Pregunta lasPreguntas[] = new Pregunta[MAX_PREGUNTAS]; /** * Agrega una pregunta al examen. Si el examen ya esta lleno, * prints un mensaje de error y no hace nada. * * @param q la pregunta a agregar */ public void agregaPregunta(Pregunta q) { if (numPreguntas == MAX_PREGUNTAS) { System.out.println("Error: excede nº maximum de preguntas para el examen"); System.exit(1); } // end if lasPreguntas[numPreguntas] = q; numPreguntas++; } // end agrega Preguntas /** * Administra el examen: busca todas las preguntas y entrega un puntaje * * @return el puntaje (en porcentaje) */ public int darExam() { int total = 0; // total de puntos en el examen int puntaje = 0; // buscar todas las preguntas for (int i = 0; i < numPreguntas; i++) { int peso = lasPreguntas[i].getPeso(); total += peso; if (lasPreguntas[i].buscar()) puntaje += peso; } // end for // reporta el puntaje, if (total == 0) { return 0; } else { double razon = (double)puntaje / total; return (int)(razon * 100 + .5); } // end if } // end darExam } // end class Exam

Ingeniería en Computación, Universidad de La Seren

178

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

ExamDemo.java Es una clase testeadora capaz de ilustrar el trabajo de cada una de las clases antes definidas, y al mismo tiempo administrar una propuesta de examen, con una solución final. /** * Un programa principal para testear. */ public class ExamDemo { /** * Este programa principal crea un pequeño examen y lo administra, tal como se espera. */ public static void main(String args[]) { // crea un examen con un total de 10 puntos: 8 preguntas de un punto y una de dos puntos Exam miExam = new Exam(); miExam.agregaPregunta(new TFpregunta("La capital de Chile es Santiago", true, 1)); String santiagoElec[] = {"Santiago", "Valparaiso", "Concepcion", "Magallanes", "Arica"}; miExam.agregaPregunta(new Selec_Mul_Pregunta("Cuál es la capital de Region Metropolitana", santiagoElec, 0, 1)); miExam.agregaPregunta(new Resp_Cortas_Pregunta("Cuál es la capital de IV Region", "Coquimbo", 1)); miExam.agregaPregunta(new TFpregunta("La capital de Alberta es Calgary", false, 1)); String BCElec[] = {"Victoria", "Vancouver", "Nanaimo"}; miExam.agregaPregunta(new Selec_Mul_Pregunta("Cuál es la capital de British Columbia", BCElec, 0, 1)); miExam.agregaPregunta(new Resp_Cortas_Pregunta("Cuál es la capital de Argentina", "Buenos Aires", 1)); miExam.agregaPregunta(new Resp_Cortas_Pregunta("Cuál es la capital de Canada", "Ottawa", 2)); miExam.agregaPregunta(new TFpregunta("La capital de La Serena es Illapel", false, 1)); String PElec[] = {"Brasilia", "Rio de Janeiro", "Sao Paulo", "Blumenau"}; miExam.agregaPregunta(new Selec_Mul_Pregunta("Cuál es la capital de Brasil?", PElec, 0, 1)); // give the exam and report the score int puntaje = miExam.darExam(); System.out.println("su resultado es " + puntaje + "%"); } // end main } // end class ExamDemo

Ingeniería en Computación, Universidad de La Seren

179

Dr. Eric Jeltsch F.

Capítulo 6: Programación Orientada a Objetos

Salida:

Condiciones de error: deberán ser TODAS cauteladas, ya sea con excepciones o asserciones. El programa principal o testeador es para fijar un estándar, no obstante si Ud. estima conveniente puede modificarlo. Pauta de Corrección: (Total 70 ptos.) 

correctness de las 4 clases:



testing (error de condiciones):



style y documentation: propuesta.)



Mapa de clases con UML documentación: 5 (Ir escogiendo alguna herramienta para el modelamiento, por ejemplo, ArgoUML, Poseidon u otra.)

15 ptos por clase(60), funcionando por separado. - 5 ptos al total. por cada ERROR.

5 (deberán contener las pruebas y testing que se le realizó a su

Ingeniería en Computación, Universidad de La Seren

180

Dr. Eric Jeltsch F.

Capitulo 7: Eventos

CAPITULO 7 Eventos (Events) La mayoría de los programas o aplicaciones comerciales responden a una amplia gama de acciones, tales como pulsar el mouse sobre un botón o pulsar una tecla de la consola. En todo caso existen otras acciones más sofisticadas, tales como cerrar windows, salvar un archivo etc. a lo que el usuario las utiliza una después de otra sin grandes dificultades. Ahora, el tipo de programas que abordaremos esta relacionada con este tipo de aplicaciones, es decir aquellas que son orientados al usuario. Java2 ofrece facilidades especiales para este propósito, en particular veremos como escribir programas que sean capaces de realizar este tipo de eventos o acciones, tales como presionar o pulsar el mouse sobre una porción de la pantalla o sobre un frame(marco), etc. Hoy en día existen herramientas que le facilitarán la vida, en términos de generar frames, textbox y otros, (por ejemplo, SUN One Studio, entre otros.), pero NO olvide que jamás podrá sustituir lo que Ud. realmente desea de la aplicación, a pesar de todo el código que pudo haber generado la herramienta. En resumen, siempre deberá entrar a manipular el código generado por la herramienta CASE, esto le responde el porque hemos empezado explicando y repasando los conceptos de POO, los que están íntimamente relacionados con los objetivos de manejar eventos. Java proporciona una biblioteca de herramientas (o clases) denominada JFC (Java Foundation Classes), con el fin de diseñar herramientas Graphic User Interface (GUI), interfaces gráficas (es decir, ventanas con componentes, tales como etiquetas, cajas de texto, botones, barras de desplazamiento, etc.) Actualmente bajo esta denominación se agrupan varias APIs: Swing. Conjunto de componentes escritos en Java para diseñar interfaces gráficas de usuario que se ejecutan uniformemente en cualquier plataforma nativa que soporta la máquina virtual de Java. AWT (Abstract Window Toolkit - kit de herramientas de ventanas abstractas). Conjunto de componentes para diseñar interfaces gráficas de usuario común a todas las plataformas nativas. Este grupo ha sido sustituido en gran medida por el conjunto de componentes Swing; muchos de éstos heredan de sus correspondientes componentes AWT. Java 2D. Permite incorporar en los programas, gráficos 2D de alta calidad, texto e imágenes. Drag and Drop. Soporte para arrastrar y colocar. Permite la transferencia de datos entre aplicaciones mediante la simple operación de arrastrarlos hasta el lugar de destino. ¿Swing o AWT?. La gran diferencia entre los componentes Swing y los componentes AWT es que los primeros están implementados absolutamente con código no nativo lo que los hace independientes de la plataforma, razón que justifica sobradamente su utilización. Además proporcionan más capacidades que los componentes AWT. Los componentes Swing se pueden identificar porque su nombre empieza por J; por ejemplo, el componente AWT Button tiene su correspondiente componente Swing JButton. Los componentes AWT se localizan en el paquete java.awt y los componentes Swing en el paquete javax.swing. Ingeniería en Computación, Universidad de La Seren

181

Dr. Eric Jeltsch F.

Capitulo 7: Eventos

Las herramientas para construir GUIs en Java pueden realizarse con Applets o a través de las aplicaciones, sin embargo los applets tienen serias rectricciones respecto del acceso al disco para nombrar o rescribir un archivo. Notar un dato importante, todos los componentes Swing son subclases de la clase JComponent. Eventos Para diseñar interfaces gráficas (llámese ventanas con componentes, cajas de texto, botones, barras de desplazamiento) java proporciona una biblioteca de clases llamada JFC (Java Foundation Classes), que cobija a Swing, AWT, Java 2D y otras API‟s. Swing o AWT?. La gran diferencia entre los componentes es que los primeros están implementados absolutamente con código no nativo lo que los hace independiente de la plataforma, además proporciona más capacidades que AWT. Los componentes de AWT se ubican en java.awt, mientras que los componentes de Swing se ubican en javax.swing. En todo caso todos los componentes Swing son subclases de la clase JComponent. Los programas en Java pueden reaccionar a un amplio rango de acciones orientadas al usuario. Por ejemplo, pulsar el mouse sobre la pantalla, ajustar los bordes del window, tipear un key sobre la consola y muchas otras. Cada una de estas acciones son llamados eventos. Ejemplo 1 import javax.swing.*; import java.awt.*; import java.awt.event.*; public class AplicacionSwing extends JFrame{ // Referencias a los componentes private JLabel etiqueta; private JButton botón; // Otras referencias private static String mensaje = "¡¡¡Hola mundo!!!"; private AplicacionSwing(String título) { // constructor super(título); // título de la ventana principal iniciarComponentes(); // Ajustar el tamaño de la ventana al mínimo pack(); } private void iniciarComponentes() { // Crear una etiqueta con el texto centrado etiqueta = new JLabel(); etiqueta.setHorizontalAlignment(JLabel.CENTER); // Crear un botón botón = new JButton("Haga clic aquí"); // Establecer como tecla aceleradora la C. Entonces, pulsar Alt+C // será equivalente ha hacer clic, sobre el botón. botón.setMnemonic(KeyEvent.VK_C); // Asignar al botón una descripción abreviada botón.setToolTipText("botón de pulsación"); // Permitir que el botón responda a los eventos de acción ActionListener al = new ActionListener() { // Este método se ejecutará cuando se haga clic en "botón" Ingeniería en Computación, Universidad de La Seren

182

Dr. Eric Jeltsch F.

Capitulo 7: Eventos

public void actionPerformed(ActionEvent evento) { Object obj = evento.getSource(); if (obj == botón) mostrarMensaje(); } }; botón.addActionListener(al); // Crear un panel para colocar los controles JPanel panel = new JPanel(); // Introducimos un borde sin pintar alrededor de los controles: // createEmptyBorder(top, left, bottom, right) panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); // Establecer un administrador de diseño de cuadrícula panel.setLayout(new GridLayout(0, 1)); // Los controles se añaden en columna (filas = 0) panel.add(etiqueta); panel.add(botón); // Añadir los componentes al contenedor de la aplicación getContentPane().add(panel, BorderLayout.CENTER); // Permitir que la ventana de la aplicación responda a los // eventos de ventana (p.e. cerrar la ventana) addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent evento) { cerrarVentana(); } } ); } private void mostrarMensaje() { // Mostrar el "mensaje" en la "etiqueta" etiqueta.setText(mensaje); } private void cerrarVentana() { // Salir de la aplicación System.exit(0); } public static void main(String[] args) { try { // Aspecto y percepción de la interfaz gráfica, look and feel UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName()); } catch (Exception e) { System.out.println("No se pudo establecer el aspecto deseado: " + e); } AplicacionSwing vPpal = new AplicacionSwing("Aplicación Swing"); vPpal.show(); } } Ingeniería en Computación, Universidad de La Seren

183

Dr. Eric Jeltsch F.

Capitulo 7: Eventos

Marco Panel Etiqueta

Botón

Ud. puede observar que cuando pulsa el botón la etiqueta muestra el mensaje ¡¡¡Hola Mundo!!!, más aún, en ella se puede observar que el botón puede activarse, además de un clic sobre el mouse, puede utilizarse las teclas aceleradoras Alt+C, y que tiene asociada una breve descripción. Ejemplo 2 import java.awt.*; import java.awt.event.*; import javax.swing.*; class ButtonPanel extends JPanel implements ActionListener { public ButtonPanel() { amaButton = new JButton("Amarillo"); azulButton = new JButton("Azul"); rojoButton = new JButton("Rojo"); add(amaButton); add(azulButton); add(rojoButton); amaButton.addActionListener(this); azulButton.addActionListener(this); rojoButton.addActionListener(this); } public void actionPerformed(ActionEvent evt) { Object source = evt.getSource(); Color color = getBackground(); if (source == amaButton) color = Color.yellow; else if (source == azulButton) color = Color.blue; else if (source == rojoButton) color = Color.red; Ingeniería en Computación, Universidad de La Seren

184

Dr. Eric Jeltsch F.

Capitulo 7: Eventos

setBackground(color); repaint(); } private JButton amaButton; private JButton azulButton; private JButton rojoButton; } class ButtonFrame extends JFrame { public ButtonFrame() { setTitle("Y mas Botones..."); setSize(300, 200); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } } ); Container contentPane = getContentPane(); contentPane.add(new ButtonPanel()); } } public class ButtonDemo { public static void main(String[] args) { JFrame frame = new ButtonFrame(); frame.show(); } }

Cuando se crean eventos, Java crea un objeto evento para representarlo. El tipo de objeto que es producido depende del orden del evento. Por ejemplo, el objeto evento que se crea para cuando pulsa el mouse pertenece a la clase MouseEvent. Existen varias otras acciones que producen objetos MouseEvent: el botón izquierdo del mouse ha sido presionado etc, o sobre el teclado con keyEvent. Una vez que ha creado el objeto de evento, Java lo pasará a un método que ha sido escogido para tratarlo como un tipo particular de evento. El método se llama event listener, (método que escucha), este método debe ser capaz de contestar apropiadamente la acción que el usuario demanda o requiere, pero para eso debió haber escogido el o los métodos apropiados. Los Ingeniería en Computación, Universidad de La Seren

185

Dr. Eric Jeltsch F.

Capitulo 7: Eventos

métodos listener tienen nombres especiales que indican el tipo de evento a los que ellos responden. Por ejemplo, un método que escucha que se ha pulsado el mouse debe responder a este evento llamado mouseClicked, si es una tecla el evento asociado es keyTyped, y así sucesivamente. (Una lista completa de sus nombres aparece a la parte final de estas notas.) Cada método que escucha tiene un solo parámetro que es el objeto de evento que representa el evento al que él está respondiendo. La vida de un programa interactivo simple, la dividiremos en dos fases. 

Fase de la estructuración. Esto puede involucrar el crear una GUI para el programa, y variables de inicialización.



Fase interactiva. Durante esta fase, el programa está esperando por los eventos comenzados por el usuario, de manera que en cuanto uno ocurra, el método correspondiente que escucha obedece. Si no hay ningún evento, el programa se “sienta” y espera hasta que otro evento venga. En general esta fase se reconoce por estar involucrados declaraciones del tipo public class MiPanel extends JPanel implements ActionListener

Si un método listener no completa su tarea lo bastante rápida, el próximo evento puede ocurrir antes de que este último haya terminado. Para manejar esta posibilidad, todos los objetos eventos se agregan a una cola de prioridades, esto se llama cola de despacho de evento (event dispatching queue). Apenas un método listener ha terminado el proceso de un evento, el próximo evento (si hay uno) en la cola se pasa al método que escucha.

GUI Minimo-Minimorum: Usualmente un programa GUI consiste de una Interface, event listener y códigos de aplicaciones. Nuestro primer programa GUI adolece de listener, pero esto no será lo usual. import java.awt.*; // import la clase AWT public class ejGUI1 { public static void main ( String[] args ) // usual start de una aplicación y no de un Applet!! { Frame frm = new Frame();//construye objeto Frame, no un Applet! frm.setSize( 150, 100 );// setea a 150 pixeles ancho y 100 alto frm.setVisible( true ); // lo hace visible, sino debe ser false. } }

Si Ud. lo ejecuto habrá notado que no tiene un event listener, pues no responde por ejemplo para cuando Ud. desea cerrar el frame, veremos como lograrlo a través de una declaración que incluye una expresión del tipo frm.addWindowListener( wquit);. Más simple aún es el siguiente programa, que en realidad no hace absolutamente nada, en realidad teoricamente crea un window, pero nunca es posible de ver el screen. import javax.swing.*; // import la clase swing Ingeniería en Computación, Universidad de La Seren

186

Dr. Eric Jeltsch F.

Capitulo 7: Eventos

public class MiniSwing1 { public static void main(String args[]) { JFrame miFrame = new JFrame(); } // end main } // end class MiniSwing1

Más simple aún a los programas anteriores es el siguiente, que en realidad muestra una barra solamente, sin dimensión para el frame. import javax.swing.*; public class MiniSwing2 { public static void main(String args[]) { JFrame miFrame = new JFrame(); miFrame.setVisible(true); } // end main } // end class MiniSwing2

Como podrá haber notado, hay que otorgarle un crédito al método setSize, pues ayudo a cambiar el tamaño del frame sobre su pantalla, incluso durante su ejecución, como lo muestra el siguiente ejemplo, pero sigue siendo un problema que el frame aparezca en la esquina superior-izquierda de su pantalla. import java.awt.*; public class ejGUI2 { public static void main ( String[] args ) { Frame frm = new Frame(); int ancho = 20; int alto = 10; frm.setVisible( true ); for ( int cont=1; cont= 0 && f.length() > 0) miTextArea.replaceRange(a.getText(), n, n + f.length()); } }); desde = new JTextField(8); miPanel.add(desde); miPanel.add(new JLabel("por")); a = new JTextField(8); miPanel.add(a); miTextArea = new JTextArea(8, 40); miScrollPane = new JScrollPane(miTextArea); contPanel.add(miPanel, "South"); contPanel.add(miScrollPane, "Center"); } private JScrollPane miScrollPane; private JTextArea miTextArea; private JTextField desde, a; } public class TextEditTest { public static void main(String[] args) { JFrame f = new TextEditFrame(); f.show(); } }

Border Sobre el panel es posible de incorporar una forma de bordes, lo que hace, que la distribución del panel o las secciones del mismo sean delimitadas. Swing ofrece una herramienta llamada border para este propósito. Ud. lo encuentra en java.awt.swing.border que proporciona la interfaces Border . Ahora veremos algunos usos comunes para esta herramienta, llamando al método static BorderFactory(). Existe una variedad de formas y estilos, algunos de ellos son: Lowered bevel, Raised bevel, Etched, Line, Matte y Empty(que es para crear un espacio en blanco alrededor del componente.) Una estructura típica de declaración de cómo agregar un borde etched con un titulo al panel es: Border etched = BorderFactory.createEtchedBorder(); Border titulo=BorderFactory.createTitledBorder(etched,“mi Titulo”); MiPanel = setBorder(titulo); Ingeniería en Computación, Universidad de La Seren

239

Dr. Eric Jeltsch F.

Capítulo 10:

Ejemplo import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; class BorderFrame extends JFrame implements ActionListener{ public BorderFrame() { JPanel botonesPanel = new JPanel(); grupo = new ButtonGroup(); addRadioButton(botonesPanel, grupo, "Lowered bevel", true); addRadioButton(botonesPanel, grupo, "Raised bevel", false); addRadioButton(botonesPanel, grupo, "Etched", false); addRadioButton(botonesPanel, grupo, "Line", false); addRadioButton(botonesPanel, grupo, "Matte", false); addRadioButton(botonesPanel, grupo, "Empty", false); Border etched = BorderFactory.createEtchedBorder(); Border titulo = BorderFactory.createTitledBorder(etched,"Tipos de Borde"); botonesPanel.setBorder(titulo); getContentPane().add(botonesPanel, "South"); setDemoPanel(); setTitle("Demo para Bordes"); setSize(600, 200); addWindowListener(new WindowAdapter(){ public void windowClosing(WindowEvent e){ System.exit(0); } } ); } public void addRadioButton(JPanel botonesPanel, ButtonGroup g, String botonNombre, boolean v) {JRadioButton button = new JRadioButton(botonNombre, v); button.addActionListener(this); g.add(button); botonesPanel.add(button); button.setActionCommand(botonNombre); } public void actionPerformed(ActionEvent evt) { setDemoPanel(); } public void setDemoPanel() { JPanel miPanel = new JPanel(); Border bordes = null; String comando = grupo.getSelection().getActionCommand(); if (comando.equals("Lowered bevel")) bordes = BorderFactory.createLoweredBevelBorder(); else if (comando.equals("Raised bevel")) bordes = BorderFactory.createRaisedBevelBorder(); else if (comando.equals("Etched")) bordes = BorderFactory.createEtchedBorder(); else if (comando.equals("Line")) bordes = BorderFactory.createLineBorder(Color.blue); else if (comando.equals("Matte")) bordes = BorderFactory.createMatteBorder(10, 10, 10, 10, Color.blue); else if (comando.equals("Empty")) bordes = BorderFactory.createEmptyBorder(); miPanel.setBorder(bordes); Ingeniería en Computación, Universidad de La Seren

240

Dr. Eric Jeltsch F.

Capítulo 10:

getContentPane().add(miPanel, "Center"); validate(); } private JPanel miPanel; private ButtonGroup grupo; } public class BorderTest { public static void main(String[] args) { JFrame frame = new BorderFrame(); frame.show(); } }

Un pequeño resumen de las librerías SWING/AWT abstract class AbstractButton void addActionListener(ActionListener l) Icon getIcon() String getText() void setIcon(Icon defaultIcon) void setIconTextGap(int iconTextGap) void setText(String texto) class ActionEvent Object getSource() String getActionCommand() interface ActionListener void actionPerformed(ActionEvent e) class BorderLayout constantes: CENTER, EAST, NORTH, SOUTH, WEST constructores:BorderLayout()BorderLayout(int hgap, int vgap)void setHgap(int hgap) Ingeniería en Computación, Universidad de La Seren

241

Dr. Eric Jeltsch F.

Capítulo 10:

void setVgap(int vgap) class Box static Box createHorizontalBox() static Box createVerticalBox() class BoxLayout (opcional) constantes: X_AXIS, Y_AXIS constructor: public BoxLayout(Container target,int axis) class Color constantes: black, blue, cyan, darkGray, gray, green, lightGray, magenta, orange, pink, red, white, yellow constructor: Color(int red, int green, int blue) abstract class Component Color getBackground() Font getFont() Color getForeground() int getHeight() int getWidth() void repaint() void setBackground(Color c) void setEnabled(boolean b) void setFont(Font f) void setForeground(Color c) void setVisible(boolean b) abstract class Container Component add(Component comp) Component add(Component comp, int index) // segunda forma para BorderLayout, use constantes void remove(Component comp) void remove(int index) void setLayout(LayoutManager manager) class FlowLayout constantes: CENTER, LEFT, RIGHT constructores: FlowLayout() FlowLayout(int align) FlowLayout(int align, int hgap,int vgap) void setAlignment(int align) void setHgap(int hgap) void setVgap(int vgap) class Font constantes: BOLD, ITALIC, PLAIN constructor:Font(String name, int style,int size) nombre de font standard: “Serif”, “SansSerif”, “Monospaced” class Frame void setTitle(String titulo) void setMenuBar(MenuBar mb) class GridLayout constructores: GridLayout(int rows, int cols) GridLayout(int rows, int cols, int hgap, int vgap) void setHgap(int hgap) void setVgap(int vgap) class ImageIcon constructor: ImageIcon(String filename) class JButton constructores: JButton() JButton(String text) JButton(Icon icon) JButton(String text, Icon icon) Ingeniería en Computación, Universidad de La Seren

242

Dr. Eric Jeltsch F.

Capítulo 10:

abstract class JComponent void setActionCommand(String accionComand) void setPreferredSize(Dimension prefeSize) // use new Dimension(width, height) class JDialog (opcional) contiene más metodos usados por JFrame: void setModal(boolean b) class JFrame constructores: JFrame() JFrame(String titulo) Container getContentPane() void setContentPane(Container c); void setBounds(int x, int y, int width, int height) void setDefaultCloseOperation(int operacion) operacion = EXIT_ON_CLOSE para salir del programa, para cuando frame es closed void setJMenuBar(JMenuBar menubar) class JLabel constantes: LEFT, CENTER, RIGHT constructores: JLabel() JLabel(String text) JLabel(String text, int horizontalAlignment) JLabel(Icon image) JLabel(String text, Icon icon, int horizontalAlignment) Icon getIcon() String getText() void setHorizontalAlignment(int alinear) void setIcon(Icon icon) void setIconTextGap(int iconTextGap) class JMenu constructores: JMenu() JMenu(String text) Component add(Component c) void addSeparator() void remove(Component c) class JMenuBar constructor: JMenuBar() JMenu add(JMenu c) class JMenuItem constructores: JMenuItem() JMenuItem(String text) JMenuItem(String text, int mnemonic) JMenuItem(Icon icon) JMenuItem(String text, Icon icon) class JPanel constructores: JPanel() JPanel(LayoutManager layout) class JTextArea constructores: JTextArea() JTextArea(int rows, int columns) JTextArea(String text) JTextArea(String text, int rows, int columns) void append(String str) void setLineWrap(boolean wrap) abstract class JTextComponent String getText() Ingeniería en Computación, Universidad de La Seren

243

Dr. Eric Jeltsch F.

Capítulo 10:

void setEditable(boolean b) void setText(String t) class JTextField constantes: LEFT, CENTER, RIGHT constructores: JTextField() JTextField(int columns) JTextField(String text) JTextField(String text, int columns) void setHorizontalAlignment(int alinear) interface LayoutManager metodos para usar internamente para cuando se implementan layout managers class Window void addWindowListener(WindowListener l) void pack()

Ingeniería en Computación, Universidad de La Seren

244

Dr. Eric Jeltsch F.

Capítulo 11:

C A P Í T U L O 11 GUI Avanzado (con Swing) En las lecturas 7-8-9-10, se entregaron los pasos preliminares para entender la filosofía que estaba detrás de las apariencias gráficas en el diseño de una interfaz de usuario. Convengamos en que el proceso de generar una interfaz de usuario, se puede realizar con herramientas de java.awt.* o de javax.swing.*. Para tal efecto, veamos la relación entre las clases que lo componen, para formarse una idea de su interrelación entre las clases. No obstante se trabaja con javax.swing, por una serie de ventajas que esta ofrece.

Menu Una observación importante es que la clase JFrame amplía la clase Frame de AWT, de manera que JFrame, JWindow y JDialog difieren de sus homólogos del AWT en que utilizan un panel de contenido separado para agregar y diseñar componentes GUI, este panel es un objeto Container al que se accede a través del método getContentPane(), método que lo hemos visto en acción en varios ejemplos hasta ahora. Los menús de Swing, al igual que las ventanas de Swing, son análogos a los AWT la diferencia fundamental es que las clases JMenuBar, JMenu, JMenuItem, JCheckBoxMenuItem y JRadioButtonMenuItem son todas ellas subclases de JComponent y por tanto de la clase Component, esto significa que los menús de Swing constituyen componentes que se pueden usar por cualquiera de las clases Container. Otra característica interesante de los menús Ingeniería en Computación, Universidad de La Seren

245

Dr. Eric Jeltsch F.

Capítulo 11:

de Swing es la propiedad de incorporar imágenes de iconos en los menús. El ejemplo siguiente muestra el uso de los menús en Swing, la metodología es la misma que se ha venido viendo, de manera que aunque el código podrá resultar grande en número de líneas, pero su estructura es muy simple. Otra herramienta de interés es el uso de JSeparator que se utiliza como separador de menús. La lógica en la generación de códigos esta dada por considerar que los elementos de menú se agregan a los menús, mientras que estos últimos se agregan a la barra de menús. Además se agregan radio-botones al correspondiente grupo de botones. La barra de menús se logra por medio del método setJMenuBar() de la clase JFrame. Aquí se aprecia un Menu típico de una GUI.

La barra de menu que podemos apreciar contiene una variedad de menus, la que se encuentra al tope de la pantalla en Windows. Toda barra de menu tiene uno o más menus, organizados por tópicos, en donde los archivos en este caso son: Archivo, Editar, Otro, etc. Por otra parte, al interior de cada uno de los menu se realizan acciones individuales tales como: Abrir, Imprimir, Cortar y Copiar, los que son mostrados para cuando Ud. activa el menu apropiado. En este caso se aprecia un SubMenu, Chequear, Radio1, Radio2 y Planta, la que a su vez tiene incorporado un archivo .gif para hacerlo más didáctico. Estas son algunas de las ventajas que ofrece Swing para trabajar con Menu, situación última que en AWT no es factible, no obstante, se puede trabajar de la misma manera en AWT, salvo restricciones, como las que se han comentado. Ya en la version Java 1.1 fue AWT totalmente elaborada incluyendo los (event handling,). JDK-Version 1.1 fue una segunda Biblioteca para programar interfaces gráficas presentada como: SWING. La que se realiza sobre AWT

Clase Menu en AWT El paquete AWT contiene cuatro clases principales para tratar los menus: java.awt.Menu java.awt.MenuBar java.awt.MenuItem java.awt.PopupMenu

Para usar menus en su aplicación Ud. necesita agregar las instancias de las tres clases, una para MenuBar con uno o más Menus, todos con varios MenuItems. Ingeniería en Computación, Universidad de La Seren

246

Dr. Eric Jeltsch F.

Capítulo 11:

La clase java.awt.MenuComponent es superclase de todas estas clases. MenuComponent extiende java.lang.Object. Los menus, barra de menu, y menu items no son componentes y no pueden ser agregadas a los contenedores en forma habitual. java.lang.Object | +---java.awt.MenuComponent | +---java.awt.MenuBar | +---java.awt.MenuItem | +---java.awt.Menu | +---java.awt.PopupMenu

Ambas MenuBar y MenuItem extienden MenuComponent. Menu extiende MenuItem. Además, MenuBar implementa la interface java.awt.MenuContainer.

La Clase MenuComponent es la raíz de la jerarquía de clases Menu. Un MenuBar representa un resumen de los Menu. Objetos de esta clase forman el punto de partida de la estructura de Menu.

Ingeniería en Computación, Universidad de La Seren

247

Dr. Eric Jeltsch F.

Capítulo 11:

Dentro de un MenuBar pueden ser organizados muchos MenuItem. Cada objeto Menu corresponde a la clase Menu de AWT. Por ejemplo, aquí se describe un sistema, del cual se puede apreciar como se correlacionan las actividades con las clases respectivas.

Hola Window Help

MenuBar

Menu

Hola

Window

Diga Hola MenuItem

Help

Mover

instance Of

Menu

Deshab Diga Hola arriba Habi Diga Hola

MenuItem

abajo

Luz(on/off)

CheckboxMenuItem

Creando Menus Es fácil construir un menu, el orden típico es 1.Crear un nuevo MenuBar. 2.Crear un nuevo Menu. 3.Agregar items al Menu. 4.Si es necesario repita etapas 2 y 3. 5.Agregar el MenuBar al Frame. Los constructores que Ud. necesita son muy simples. Por ejemplo, para crear un objeto nuevo MenuBar, basta con declarar: MenuBar miMenubar = new MenuBar();

Para crear un nuevo Menu use el constructor Menu(String titulo). Pasando el titulo al menu que Ud, desee. Por ejemplo, para crear los menus Archivo y Editar, basta con declarar, Menu miArchivoMenu = new Menu("Archivo"); Menu miEditarMenu = new Menu("Editar"); Ingeniería en Computación, Universidad de La Seren

248

Dr. Eric Jeltsch F.

Capítulo 11:

MenuItems

son creados en forma similar con el constructor MenuItem(String menutext). Pasando el titulo del menu que Ud. quiera, por ejemplo, MenuItem Cortar = new MenuItem("Cortar");

También puede crear MenuItems al interior de los menus, por ejemplo: Cortar, Copiar, Pegar, Limpiar y seleccionar todos los MenuItems: Menu editMenu = new Menu("Edit"); editMenu.add(new MenuItem("Cortar")); editMenu.add(new MenuItem("Copiar")); editMenu.add(new MenuItem("Pegar")); editMenu.add(new MenuItem("Limpiar")); editMenu.addSeparator(); editMenu.add(new MenuItem("Seleccionar Todos"));

El método addSeparator() agrega una línea horizontal al menu. Esto es usado para separar logicamente las funciones del menu. Luego podrá incorporar al Menu, las barras del Menu usando MenuBares(Menu m), por ejemplo,: miMenubar.add(ArchivoMenu); miMenubar.add(EditarMenu);

Finalmente, para cuando la barra de menu estime que esta copada, se procede a incorporarla al Frame usando el método frame setMenuBar(MenuBar mb). Dado un Frame f , este es un ejemplo: f.setMenuBar(miMenuBar); Ejemplos import java.awt.Frame; public class AWT_Ej1 { public static void main(String[] args) { Frame wnd = new Frame("Simple Ventana"); wnd.setSize(400,300); wnd.setVisible(true); } //end main() } //class AWT_Ej1, genera una ventana simple sin la posibilidad de cerrar. import import import import

java.awt.Frame; java.awt.Window; java.awt.event.WindowAdapter; java.awt.event.WindowEvent;

public class AWT_Ej2 { public static void main(String[] args) { Frame wnd = new Frame("Simple Ventana, pero se cierra!"); wnd.addWindowListener( new WindowCierreAdapter() ); wnd.setSize(400,300); wnd.setVisible(true); } //main() Ingeniería en Computación, Universidad de La Seren

249

Dr. Eric Jeltsch F.

Capítulo 11:

} //class AWT_Ej2, genera una ventana simple con la posibilidad de cerrar. class WindowCierreAdapter extends WindowAdapter { public void windowClosing( WindowEvent we) { Window wnd = we.getWindow(); wnd.setVisible(false); wnd.dispose(); System.exit(0); } //windowClosing() } //class WindowCierreAdapter

Clase JMenu en Swing La clase JMenuBar contiene los métodos necesarios para manejar una barra de menú, que es a su vez un contenedor de menús. La clase JMenu contiene los métodos para manejar los menús, por ejemplo cuando un menú es cliqueado el menú se expande para mostrar una lista de los items menú. Hacer click sobre un menú genera un evento y por tal motivo deberemos contar con “escuchadores” o listener. La clase JMenuItem contiene los métodos para manejar items de menú, pudiendo ser un submenú que proporciona a su vez más menús. La clase JCheckBoxMenuItem contiene los métodos para manejar items de menú según una forma particular de chequeo. La clase JRadioButtonMenuItem muestra una forma de circulo relleno para optar por alguna opción dentro de un menú. Creando Menus JMenuBar miMenuBar = new JMenuBar();

Si quiere agregarle métodos, bastará con una declaración del tipo: MiFrame.setJMenuBar(miMenuBar);

Ahora, si desea para cada menú crear un objeto menú, JMenu editarMenu= new JMenu(“Edit”);

Pudiendo agregar menu items, por ejemplo, separadores, JMenuItem archivoNew = new JMenuItem("New"); editarMenu.add(archivoNew); editarMenu.addSeparator();

o submenús a objetos menú, por ejemplo, en este mismo contexto, JMenu opcionMenu=...; editarMenu.add(opcionMenu);

para luego accesarlo a la barra del menú, MiMenuBar.addMenu(editarMenu);

El efecto de seleccionar un menú, significa que se gatilla una acción representada por los eventos, por eso que se necesita instalar un escuchador o listener para cada menú items. Algo parecido a, ArchivoNew.addActionListener(this), si Ud. se da cuenta esta forma de construcción para cuando se tienen varios menús y submenús es muy tedioso, de ahí que es recomendable Ingeniería en Computación, Universidad de La Seren

250

Dr. Eric Jeltsch F.

Capítulo 11:

usar un procedimiento que lo realice. Nosotros mostramos dos modalidades. En este ejemplo se muestra la primera modalidad en donde se realiza:   



una inicialización de las variables globales que toman parte en el programa, luego continua con la declaración de la barra de menú (Archivo), creando cada uno de los componentes de cada segmento, en el ejemplo, me refiero a (Sobre y Exit), incorporandole de inmediato un addActionsListener(), que va a realizar el despliegue de un mensaje para cuando el escuchador apropiado haya escuchado este evento(Sobre) o se saldrá si escucho (Exit). Esto así construído se incorpora a la barra de manú. De la misma manera se crea (Formato), que tiene otras habilidades, como (Colores) y (Fuentes). Se crean las clases ItemTrato y EstiloTrato que implementaran la inteface apropiada de ActionListener e ItemListener con los métodos actionPerformed() e ItemStateChanged().

Ejemplo: import javax.swing.*; import java.awt.event.*; import java.awt.*; public class MenuTest extends JFrame { private Color colorValor[]={Color.black,Color.blue,Color.red,Color.green}; private JRadioButtonMenuItem colorItems[], fonts[]; private JCheckBoxMenuItem estiloItems[]; private JLabel desplegar; private ButtonGroup miFontGroup, miColorGroup; private int estilo; public MenuTest() { super( "Usando JMenus" ); JMenuBar miBar = new JMenuBar(); // crea menubar setJMenuBar( miBar );// setea el menubar para JFrame // crea los archivos del Menu , entre ellos Sobre y //Exit como menu item JMenu miFileMenu = new JMenu( "Archivo" ); JMenuItem sobreItem = new JMenuItem( "Sobre..." ); sobreItem.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { JOptionPane.showMessageDialog( MenuTest.this, "Este es un ejemplo\nde usos de menus", "Sobre", JOptionPane.PLAIN_MESSAGE ); } } ); miFileMenu.add( sobreItem ); JMenuItem exitItem = new JMenuItem( "Exit" ); exitItem.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { Ingeniería en Computación, Universidad de La Seren

251

Dr. Eric Jeltsch F.

Capítulo 11:

System.exit( 0 ); } } ); miFileMenu.add( exitItem ); miBar.add( miFileMenu ); // los agrega al File menu // crea el otro segmento de menu, y sus submenus como menu //items. JMenu formatMenu = new JMenu( "Formato" ); // crea Color como submenu, inicializando colores. String colores[] = { "Black", "Blue", "Red", "Green" }; JMenu colorMenu = new JMenu( "Color" ); colorItems = new JRadioButtonMenuItem[ colores.length ]; miColorGroup = new ButtonGroup(); ItemTrato itemTrato = new ItemTrato(); for ( int i = 0; i < colores.length; i++ ) { colorItems[ i ] = new JRadioButtonMenuItem( colores[ i ] ); colorMenu.add( colorItems[ i ] ); miColorGroup.add( colorItems[ i ] ); colorItems[ i ].addActionListener( itemTrato ); } colorItems[ 0 ].setSelected( true ); formatMenu.add( colorMenu ); formatMenu.addSeparator(); // crea Font como submenu, inicializando fuentes. String fontNombres[] = { "TimesRoman", "Courier", "Helvetica" }; JMenu fontMenu = new JMenu( "Fuentes" ); fonts = new JRadioButtonMenuItem[ fontNombres.length ]; miFontGroup = new ButtonGroup(); for ( int i = 0; i < fonts.length; i++ ) { fonts[ i ] = new JRadioButtonMenuItem( fontNombres[ i ] ); fontMenu.add( fonts[ i ] ); miFontGroup.add( fonts[ i ] ); fonts[ i ].addActionListener( itemTrato ); } fonts[ 0 ].setSelected( true ); fontMenu.addSeparator(); String estiloNombres[] = { "Bold", "Italic" }; estiloItems = new JCheckBoxMenuItem[ estiloNombres.length ]; EstiloTrato estiloTrato = new EstiloTrato(); for ( int i = 0; i < estiloNombres.length; i++ ) { estiloItems[ i ] = new JCheckBoxMenuItem( estiloNombres[ i ] ); fontMenu.add( estiloItems[ i ] ); estiloItems[ i ].addItemListener( estiloTrato ); } formatMenu.add( fontMenu ); miBar.add( formatMenu ); // agrega formato al menu Ingeniería en Computación, Universidad de La Seren

252

Dr. Eric Jeltsch F.

Capítulo 11:

desplegar = new JLabel("Muestras de Texto", SwingConstants.CENTER ); desplegar.setForeground( colorValor[ 0 ] ); desplegar.setFont( new Font( "TimesRoman", Font.PLAIN, 72 ) ); getContentPane().setBackground( Color.cyan ); getContentPane().add( desplegar, BorderLayout.CENTER ); setSize( 500, 200 ); show(); } public static void main( String args[] ) { MenuTest app = new MenuTest(); app.addWindowListener( new WindowAdapter() { public void windowClosing( WindowEvent e ) { System.exit( 0 ); } } ); } class ItemTrato implements ActionListener { public void actionPerformed( ActionEvent e ) { for ( int i = 0; i < colorItems.length; i++ ) if ( colorItems[ i ].isSelected() ) { desplegar.setForeground( colorValor[ i ] ); break; } for ( int i = 0; i < fonts.length; i++ ) if ( e.getSource() == fonts[ i ] ) { desplegar.setFont( new Font( fonts[ i ].getText(), estilo, 72 ) ); break; } repaint(); } } class EstiloTrato implements ItemListener { public void itemStateChanged( ItemEvent e ) { estilo = 0; if ( estiloItems[ 0 ].isSelected() ) estilo += Font.BOLD; if ( estiloItems[ 1 ].isSelected() ) estilo += Font.ITALIC; desplegar.setFont( new Font( desplegar.getFont().getName(), estilo, 72 ) );

Ingeniería en Computación, Universidad de La Seren

253

Dr. Eric Jeltsch F.

Capítulo 11:

repaint(); } } }

Como otra forma de construir menús he considerado, setupEventos(), que es una estructura en donde depósito todos los eventos, tal como se muestran en el siguiente ejemplo. Existe otra forma, más elegante en el texto de Core Java2 de Hortsmann, pág 489, de cómo organizar los menús y submenús. Ejemplo import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; public class SwingWin extends JFrame { public static int WIDTH = 300; public static int HEIGHT = 300; public static String TITULO = "SwingWin"; Container miframeContainer; // Swing componentes JTextField miTextField = new JTextField(50); JMenuBar miMenuBar = new JMenuBar(); Ingeniería en Computación, Universidad de La Seren

254

Dr. Eric Jeltsch F.

Capítulo 11:

JMenu archivoMenu = new JMenu("File"); JMenuItem archivoNew = new JMenuItem("New"); JMenuItem archivoOpen = new JMenuItem("Open"); JMenuItem archivoSave = new JMenuItem("Save"); JMenuItem archivoExit = new JMenuItem("Exit"); JMenu editarMenu = new JMenu("Edit"); JMenuItem editarCut = new JMenuItem("Cut"); JMenuItem editarCopy = new JMenuItem("Copy"); JMenuItem editarPaste = new JMenuItem("Paste"); JMenu especialMenu = new JMenu("Special"); JCheckBoxMenuItem especialCheck1 = new JCheckBoxMenuItem("Check 1"); JCheckBoxMenuItem especialCheck2 = new JCheckBoxMenuItem("Check 2",true); JSeparator miSeparador = new JSeparator(); JRadioButtonMenuItem especialRadio1 = new JRadioButtonMenuItem("Radio 1"); JRadioButtonMenuItem especialRadio2 = new JRadioButtonMenuItem("Radio 2"); ButtonGroup miButtonGroup = new ButtonGroup(); public SwingWin() { super(TITULO); //el constructor SwingWin invoca a miGui()para construir la //GUI del programa y a setupEventos()para conectar eventos //a su código de manejo de eventos. miGUI(); setupEventos(); setSize(WIDTH,HEIGHT); show(); } void miGUI() { //el método setupMenuBar es invocado por el constructor //miGUI(), para configurar la barra de menús del programa. setupMenuBar(); layoutComponentes(); } void setupMenuBar() { archivoMenu.add(archivoNew); archivoMenu.add(archivoOpen); archivoMenu.add(archivoSave); archivoMenu.add(archivoExit); editarMenu.add(editarCut); editarMenu.add(editarCopy); editarMenu.add(editarPaste); especialMenu.add(especialCheck1); especialMenu.add(especialCheck2); especialMenu.add(miSeparador); miButtonGroup.add(especialRadio1); miButtonGroup.add(especialRadio2); especialMenu.add(especialRadio1); especialMenu.add(especialRadio2); miMenuBar.add(archivoMenu); miMenuBar.add(editarMenu); miMenuBar.add(especialMenu); setJMenuBar(miMenuBar);//organiza el cuento. } //este método invoca al método getContentPane() de la clase //Jframe con el fin de obtener el container del frame public void layoutComponentes() { miframeContainer = getContentPane(); miframeContainer.setLayout(null); miTextField.setBounds(150,150,100,20); miframeContainer.add(miTextField); } //este método configura los manipuladores de eventos de la //ventana y de cada uno de los elementos de menú. Ingeniería en Computación, Universidad de La Seren

255

Dr. Eric Jeltsch F.

Capítulo 11:

void setupEventos() { addWindowListener(new WindowTrato()); archivoNew.addActionListener(new MenuItemTrato()); archivoOpen.addActionListener(new MenuItemTrato()); archivoSave.addActionListener(new MenuItemTrato()); archivoExit.addActionListener(new MenuItemTrato()); editarCut.addActionListener(new MenuItemTrato()); editarCopy.addActionListener(new MenuItemTrato()); editarPaste.addActionListener(new MenuItemTrato()); especialCheck1.addItemListener(new ItemTrato()); especialCheck2.addItemListener(new ItemTrato()); especialRadio1.addItemListener(new ItemTrato()); especialRadio2.addItemListener(new ItemTrato()); } public static void main(String[] args) { SwingWin app = new SwingWin(); } public class WindowTrato extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } } public class MenuItemTrato implements ActionListener { public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); if(cmd.equals("Exit")) System.exit(0); else miTextField.setText(cmd); } } public class ItemTrato implements ItemListener { public void itemStateChanged(ItemEvent e) { AbstractButton boton = (AbstractButton) e.getItem(); String miLabel = boton.getText(); if(boton.isSelected()) miLabel += " true"; else miLabel += " false"; miTextField.setText(miLabel); } } }

Esta es una parte de su ejecución.

Ingeniería en Computación, Universidad de La Seren

256

Dr. Eric Jeltsch F.

Capítulo 11:

Como ya lo han visto Swing puede considerar label como rotulos en los menús, pero esto no es todo pues también considera iconos o ambos, basta con declarar una expresión del tipo, JMenuItem editarItem = new JMenuItem(“Cut”, new ImageIcon(“cut.gif”)); otras interfaces posibles de generar son

Ingeniería en Computación, Universidad de La Seren

257

Dr. Eric Jeltsch F.

Capítulo 11:

Cuyo código está en miMenuSimple.java. import java.awt.*; import java.awt.event.*; import javax.swing.*; public class miMenuSimple extends JMenuBar implements ActionListener { String[] archivoItems = new String[] { "Nuevo", "Abrir", "Salvar", "Exit" }; String[] editarItems = new String[] { "Cortar", "Copiar", "Pegar" }; char[] archivoCortito = { 'N','A','S','E' }; char[] editarCortito = { 'T','C','P' }; public miMenuSimple() { JMenu archivoMenu = new JMenu("Archivo"); JMenu editarMenu = new JMenu("Editar"); JMenu otroMenu = new JMenu("Otro"); JMenu subMenu = new JMenu("SubMenu"); JMenu subMenu2 = new JMenu("SubMenu2"); // Ensamblar el archivo menu con abreviaciones. for (int i=0; i < archivoItems.length; i++) { JMenuItem item = new JMenuItem(archivoItems[i], archivoCortito[i]); item.addActionListener(this); archivoMenu.add(item); } // Ensamblar el archivo menus con los aceleradores de teclado. for (int i=0; i < editarItems.length; i++) { JMenuItem item = new JMenuItem(editarItems[i]); item.setAccelerator(KeyStroke.getKeyStroke(editarCortito[i], java.awt.Event.CTRL_MASK, false)); item.addActionListener(this); editarMenu.add(item); } // Insertar un separador en el menú Editar editarMenu.insertSeparator(1); // Ensamblar los submenús de Otro Menu JMenuItem item; subMenu2.add(item = new JMenuItem("Extra 2")); Ingeniería en Computación, Universidad de La Seren

258

Dr. Eric Jeltsch F.

Capítulo 11:

item.addActionListener(this); subMenu.add(item = new JMenuItem("Extra 1")); item.addActionListener(this); subMenu.add(subMenu2); // Ensamblar Otro Menu en si mismo otroMenu.add(subMenu); otroMenu.add(item = new JCheckBoxMenuItem("Chequear")); item.addActionListener(this); otroMenu.addSeparator(); ButtonGroup buttonGroup = new ButtonGroup(); otroMenu.add(item = new JRadioButtonMenuItem("Radio 1")); item.addActionListener(this); buttonGroup.add(item); otroMenu.add(item = new JRadioButtonMenuItem("Radio 2")); item.addActionListener(this); buttonGroup.add(item); otroMenu.addSeparator(); otroMenu.add(item = new JMenuItem("Planta", new ImageIcon("image.gif"))); item.addActionListener(this); // Finalmente agrega todos los menús al menubar add(archivoMenu); add(editarMenu); add(otroMenu); } public void actionPerformed(ActionEvent event) { System.out.println("Menu item [" + event.getActionCommand() + "] fue presionado."); } public static void main(String s[]) { JFrame frame = new JFrame("Un Simple Menu"); //frame.addWindowListener(new BasicWindowMonitor()); frame.setJMenuBar(new miMenuSimple()); frame.pack(); frame.setVisible(true); } }

Para concluir al menos en esta parte les mostrare el último ejemplo en el mismo contexto de lo tratado hasta ahora, la única novedad es la herramienta llamada Look andFeel, que es capaz de simular interfaces de Motif, Windows que son interfaces gráficas de sistemas propietarios. Al archivo le he llamado SwingLF.java import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.border.*; import com.sun.java.swing.plaf.motif.*; import javax.swing.plaf.metal.*; import com.sun.java.swing.plaf.windows.*; public class SwingLF extends JFrame { public static int WIDTH = 450; public static int HEIGHT = 450; Ingeniería en Computación, Universidad de La Seren

259

Dr. Eric Jeltsch F.

Capítulo 11:

public static String TITULO = "SwingLF"; //defino mi contenedor Container miframeContainer; // defino los Swing componentes JPanel[] paneles = new JPanel[6]; //botones de chequeo JCheckBox checkbox1 = new JCheckBox("Check 1"); JCheckBox checkbox2 = new JCheckBox("Check 2"); JCheckBox checkbox3 = new JCheckBox("Check 3"); //botones de selección JRadioButton radioButton1 = new JRadioButton("Radio 1"); JRadioButton radioButton2 = new JRadioButton("Radio 2"); JRadioButton radioButton3 = new JRadioButton("Radio 3"); //campos de texto JTextField textField1 = new JTextField("Text field 1",15); JTextField textField2 = new JTextField("Text field 2",15); //barras deslizantes JSlider slider1 = new JSlider(0,0,100,25); JSlider slider2 = new JSlider(0,0,100,75); //botones que cambian el “look” JButton metalButton = new JButton("Metal"); JButton motifButton = new JButton("Motif"); JButton windowsButton = new JButton("Windows"); //construyo la barra de menú JMenuBar miMenuBar = new JMenuBar(); //construyo los componentes de la barra “Archivo” JMenu archivoMenu = new JMenu("Archivo"); JMenuItem archivoNuevo = new JMenuItem("Nuevo"); JMenuItem archivoAbrir = new JMenuItem("Abrir"); JMenuItem archivoSalvar = new JMenuItem("Salvar"); JMenuItem archivoSalir = new JMenuItem("Salir"); //construyo los componentes de la barra “Editar” JMenu editarMenu = new JMenu("Editar"); JMenuItem editarCortar = new JMenuItem("Cortar"); JMenuItem editarCopiar = new JMenuItem("Copiar"); JMenuItem editarPegar = new JMenuItem("Pegar"); //clases LookAndFeel MetalLookAndFeel metalLF = new MetalLookAndFeel(); MotifLookAndFeel motifLF = new MotifLookAndFeel(); WindowsLookAndFeel windowsLF = new WindowsLookAndFeel(); public SwingLF() { //SwingLF carretero super(TITULO); miGUI(); setupEventos(); setSize(WIDTH,HEIGHT); show(); } //miGUI carretera void miGUI() { setupMenuBar(); layoutComponentes(); } void setupMenuBar() { archivoMenu.add(archivoNuevo); archivoMenu.add(archivoAbrir); archivoMenu.add(archivoSalvar); archivoMenu.add(archivoSalir); miMenuBar.add(archivoMenu); Ingeniería en Computación, Universidad de La Seren

260

Dr. Eric Jeltsch F.

Capítulo 11:

editarMenu.add(editarCortar); editarMenu.add(editarCopiar); editarMenu.add(editarPegar); miMenuBar.add(editarMenu); setJMenuBar(miMenuBar); } public void layoutComponentes() { for(int i=0;i