Java - ITS USER ID
Transcripción
Java - ITS USER ID
Notas del Curso de ACM: Java SE v. 2009 Notas de Java SE 2009 Dr. Manuel Mora T. 1/ 150 OUTLINE 1. Introducción. 2. Variables. 3. Operadores. 4. Decisionales e Iteradores. 5. Definición de Clases y Objetos. 6. Organización de Proyectos. 7. Números y Strings. 8. Interfaces. 9. Herencia entre Clases. 10. Flujos de E/S. 11. Excepciones. 12. Genéricos. 13. Colecciones. 14. Concurrencia. 15. Applets. 16. GUI Swing. 17. JDBC. Notas de Java SE 2009 Dr. Manuel Mora T. 2/ 150 1. Introducción. Características de Java: • • • • • Lenguaje sucesor de C/C++ Estrictamente Orientado a Objetos (no híbrido). • Abstración (clases genéricas como moldes de otras clases) • Encapsulamiento (atributos y métodos usualmente protegidos, pero accesibles) • Herencia (no múltiple como C++, pero el uso de <interfaces> es un modo alternativo) • Polimorfismo (métodos con diferentes firmas /sobrecargados) Distribuido, Seguro y Simple (código llamable desde otras máquinas en ambiente cliente-servidor normal o web, no instrucciones directas para afectar archivos, un set simple de keywords (50) (pero el uso de bibliotecas adicionales requerirá bastante más intrucciones (Java API clases: implícitas o importables (java.awt, java.io, java.util, java.net, java.applet, etc. NOTA: se importa con: import <nombre-paquete>.<nombre-clase>; import <nombre-paquete>.*; ) Multiversión (SE (estándar), EE (empresarial), ME (móvil) Multiplataforma vía VJM (implantado en un JRE) Notas de Java SE 2009 Dr. Manuel Mora T. 3/ 150 1. Introducción. The Java Programming Language The Java programming language is a high-level language that can be characterized by all of the following buzzwords: •Simple •Architecture neutral •Object oriented •Portable •Distributed •High performance •Multithreaded •Robust •Dynamic •Secure In the Java programming language, all source code is first written in plain text files ending with the .java extension. Those source files are then compiled into .class files by the javac compiler. A .class file does not contain code that is native to your processor; it instead contains bytecodes — the machine language of the Java Virtual Machine1 (Java VM). The java launcher tool then runs your application with an instance of the Java Virtual Machine. An overview of the software development process. Because the Java VM is available on many different operating systems, the same .class files are capable of running on Microsoft Windows, the Solaris TM Operating System (Solaris OS), Linux, or Mac OS.. Through the Java VM, the same application is capable of running on multiple platforms. Notas de Java SE 2009 Dr. Manuel Mora T. 4/ 150 1. Introducción. • Keywords enJava (50): abstract assert switch continue default synchronized boolean do this break double throw byte else throws case enum transient catch extends try char final void class finally volatile const float while for new goto package if private implements protected import public instanceof return int short interface static long strictfp native super + true, false, null (son literales) NOTA: goto y const NO SON USADAS en Java al presente Notas de Java SE 2009 Dr. Manuel Mora T. 5/ 150 1. Introducción. Ambiente Básico Java SE: • • • JDK + JRE requerido (1.5 en adelante) Editor o Ambiente integrado (como Netbeans o Eclipse) Documentación en: http/java.sun.com/javase/6/docs/api/ Proceso Básico: • • • Con editor se crean clases con formato: clase>.java <nombre- (archivo fuente puede tener 1 o más clases, pero solo 1 clase es de tipo <public>, y en este caso el nombre de dicha clase es el mismo del archivo fuente. El orden de elementos es: declaración de paquetes + importaciones de clases + declaración de clases) Se compilan con: javac <nombre-clase>.java lo cual genera un archivo: <nombre-clase>.class (se puede mandar llamar compilar 1 clase, y el compilador mandará llamar a las otras clases) Se ejecutan con: java <nombre-clase> NOTA: verificar variables de instalación PATH (debe tener la ruta de <java root>/bin , donde <java root> es el directorio de instalación de JRE o JDK usado. PATH es el directorio de las clases de java. CLASSPATH es el directorio donde java espera las clases ( .java) definida por usuarios. To set the CLASSPATH variable, use these commands (for example): C:\> set CLASSPATH=C:\...\java\classes Notas de Java SE 2009 Dr. Manuel Mora T. 6/ 150 1. Introducción. Java: • • • • Lenguaje de Programación (DOS, GUI, C/S, web) Ambiente de Desarrollo (compilador + interpretador JVM + generador de documentación + herramienta para empacar clases). Ambiente de Despliegue (JRE o Web-browser) Ambiente de Aplicación (standalone o web) Java: • • • • Manejo de asignación/liberación de memoria de manera automática y dinámica. Bytecodes para JVM (formato compacto + formato eficiente) JVM define: set de instrucciones, set de registros, formatos de archivos de clases, stack de ejecución, manejo de heap, manejo de memoria, manejo de errores fatales, soporte para manejo preciso de reloj. JVM proceso consiste en: load (clases), verify (bytecodes), execute (interpretar bytecodes) • Load (carga clases locales en un espacio + clases de red en otro espacio) • Verify (realiza 4 verificaciones sobre: formato de archivos de clase, no violaciones de acceso a objetos, no problemas de stack overflow, paramétros de tipos correctos y conversiones de datos correctas). Clases descargadas de la red, son también verificadas. • Execute (se realiza en la implantación particular JRE de la JVM general especificación. El interpretador ejecuta bytecodes y realiza llamadas a hardware. En algunos JRE, algunas secciones de bytecodes son realmente compilados a código nativo de la máquina (con lo cual la velocidad es similar a C++). Notas de Java SE 2009 Dr. Manuel Mora T. 7/ 150 1. Introducción. Java comments, statements, blocks e Identificadores: • Comments in Java: • // una línea • /* multi-línea */ • /** comentarios de entrada a JavaDoc */ • statements Instrucciones que terminan con ; • Blocks Conjunto de instrucciones entre { } • Identificadores - Pueden comenzar con : letra, _, $ - Se distinguen mayúsculas y minúsculas - Longitud no limitada Notas de Java SE 2009 Dr. Manuel Mora T. 8/ 150 2. Variables. • Variables pueden ser de 2 tipos: Class Types y Primitive Types. • Variables Globales (fuera de métodos, pero dentro de una clase, son inicializadas por default) • Variables de Clase (usan <static>, existen mientras la clase esté cargada) • Variables de Atributo/de Miembros/de Instancias. • Variables (sin <static>) • Cada objeto las instancía a un valor particular • Almacenadas en el heap (montón de espacio disponible) • Variables Locales • Variables definidas dentro de métodos, o blocks de código • Existen solo el tiempo de vida de los métodos o block de código • Almacenadas en el stack de ejecución • Necesitan ser inicializadas • Variables pueden sostener referencias (no se requieren pointers. E.g. <variable> = new <tipo> ). NOTA: new produce la secuencia siguiente (1. asignar memoria. 2. explícita inicialización (por declaración de la clase). 3 llamada a constructor. 4. retorno de referencia) • Variables deben ser declaradas antes de usarse. • Java es <case sensitive> ! Estándar de nombres es usar: minúsculas y en caso de varias palabras pegadas, iniciar cada una mayúscula. Notas de Java SE 2009 Dr. Manuel Mora T. 9/ 150 2. Variables. • Tipos básicos y definición de variables en Java (como atributos de clases o en métodos): <public/private/final> <tipo> <nombre1>, …, <nombreK>; • Tipos Primitivos : • Integral: byte (8 bits), short (16 bits) , int (32 bits), long (64 bits, usar L al final) ( O…., Ox….., para octal o hexadecimal representación. Default es int, y para especificar que es Long, usar L al final (ejemplo: 0x000AL) • Floating: float (32 bits) (usar F al final del valor), double (64 bits, default), se puede usar notación exponencial número E spotencia) • Textual: char (16 bits) (usar ‘ ‘ para valor, o ‘\symbol’ o ‘\uHHHH’) donde HHHH es el cógido en hexadecimal • Logical: boolean • String (no es un primitivo tipo) (usar “ ….. ”) Inicialización: • <tipo> <var1> =<valor/expresión>, <var2>= <valor/expresión>, … ; • NOTA: <final> es usado para declarar constantes. Por convención el nombre de constantes es en formato: MAYUSCULAS_MAYUSCULAS. Notas de Java SE 2009 Dr. Manuel Mora T. 10/ 150 2. Variables. Constants • The static modifier, in combination with the final modifier, is also used to define constants. The final modifier indicates that the value of this field cannot change. • For example, the following variable declaration defines a constant named PI, whose value is an approximation of pi (the ratio of the circumference of a circle to its diameter): static final double PI = 3.141592653589793; • Constants defined in this way cannot be reassigned, and it is a compile-time error if your program tries to do so. By convention, the name of constant values are spelled in uppercase letters. If the name is composed of more than one word, the words are separated by an underscore (_). Notas de Java SE 2009 Dr. Manuel Mora T. 11/ 150 2. Variables. Arreglos: declaraciones, instanciaciones e inicializaciones en Java: Declaración de Arreglos (no se especifica longitud del arreglo): • • <tipo> [ ][ ] … [ ] <nombre-arreglo>; <tipo> <nombre-arreglo> [ ][ ] … [ ]; Arreglos son usados por referencias (necesitan el comando <new> para instanciarlo): • • <nombre-arreglo> = new <tipo> [longitud]; <nombre-arreglo> = new <tipo> [longitud 1] … [longitud k]; NOTA: <tipo> puede ser una <clase> Inicialización de arreglos: • • • • • • <tipo>[ ] <nombre-arreglo> = { <v1>, <v2>, …, <vk> }; <tipo>[ ] <nombre-arreglo> = new <tipo>[ ] { … } <tipo> <nombre-arreglo>[ ] = { <v1>, <v2>, …, <vk> }; <tipo> <nombre-arreglo>[ ] = new <tipo>[ ] { … } <tipo-clase>[ ] <nombre-arreglo> = { new <constructor>(parms), …, }; <tipo-clase>[ ] <nombre-arreglo> = new <tipo>[ ] { new <constructor>(parms), …, }; NOTAS: <arreglo>.length guarda el número de elementos en el arreglo, y el primero es arreglo[0]. No se puede re-dimensionar el arreglo, pero se puede re-usar la referencia. System.arraycopy(…) Sirve para copiar arreglos. Notas de Java SE 2009 Dr. Manuel Mora T. 12/ 150 2. Variables. Instanciaciones e Inicializaciones en Java de Strings: • String no es un primitivo de Java, y variables de este tipo pueden ser declaradas en 2 formas: • • • String <var> = new String(“valor inicial”); String <var> = “valor inicial”; // ahora memoria al evitar duplicados Equals Notas de Java SE 2009 Dr. Manuel Mora T. 13/ 150 3. Operadores Numéricos: (usar: tipos int, o mayores; byte and short son promovidos automáticamente con posible error de compilación) + * / % (devuelve entero remanente de una división) Incrementadores/Decrementadores unitarios: ++<variable>; --<variable>; <variable>++; <variable>--; Orden de ejecución por peso: 1.- ( ) 2.- incrementadores/decrementadores 3.- * y / de izquierda a derecha 4.- + y – de izquierda a derecha 5.- de peso similar, de izquierda a derecha NOTA: Asignación de tipos de variables deben ser compatibles o bien usar <type casting> o <promoción>. Ejemplo de <casting>: <var> = (tipo) <expresion>; Notas de Java SE 2009 Dr. Manuel Mora T. 14/ 150 3. Operadores Relacionales: == != < <= > >= && || ! and or Not ~ & | ^ not and or xor Notas: a nivel bits a nivel de bits a nivel de bits a nivel de bits 1.- Para Strings, la comparación usando == puede fallar, dependiendo si los strings se crearon con new (fallaría) or no. Debe usarse, siempre en su lugar el método de la clase String.equals( ). 2. Zero no es considerado false y un valor <> de zero no es considerado true. Más bien, marcaría error de compilación o ejecución tal comparación. 3. Operadores de shift : N >> M divide N por 2^M N << M multiplica N por 2^M | B >> C B >>> C Notas de Java SE 2009 sobre bits inserta bit de signo C veces a la izq. de B sobre bits inserta the bit 0 C veces a la izq. de B Dr. Manuel Mora T. 15/ 150 4. Decisionales e Iteraciones • Decisionales sirven para dirigir el flujo de ejecución a un bloque en particular, dependiendo del resultado de una expresión condicional (true o false). if (<condición>) { } if (<condición>) { } else { } if (<condición>) { } else if ( <condición>) { } else if ( <condicion>) { } else { } Notas de Java SE 2009 Dr. Manuel Mora T. 16/ 150 4. Decisionales e Iteraciones switch (<variable>) { case <val-caso1>: … break; case <val-caso2>: … break; case <val-caso3>: … break; … case <val-casoK>: … break; default: } NOTA: variable debe ser de tipo: byte, short, int , char, o un tipo enumerado, o un n elementos constantes. <break><label>; y <label>: combinación funciona como <goto> Notas de Java SE 2009 Dr. Manuel Mora T. 17/ 150 4. Decisionales e Iteraciones • Iteraciones son instrucciones para ejecutar 0, 1 o n veces un bloque de código, basado en una condición. Zero-to-many loop: while (<condición> { } 1-to-many loop: do { } while (<condición> ); Zero-to-many loop: for ( <inicio>; <condición-de-hacer-ciclo>; <incremento>) { } NOTAS: <incremento> se ejecuta luego de bloque de for. Existe un <continue> estatuto para romper ciclo. Se puede usar en while, do o for. Notas de Java SE 2009 Dr. Manuel Mora T. 18/ 150 4. Decisionales e Iteraciones • El ciclo <for> tiene varias variantes: // declarar variable dentro del for for (int i=0; i<10; i++) { } // usar for mejorado/enhanced cuando hay arreglos int [ ] arreglo = {1,3,5 } for (int i : arreglo) { } Notas de Java SE 2009 Dr. Manuel Mora T. 19/ 150 5. Definición de Clases y Objetos. • Clases son los moldes básicos para definir otras clases (con atributos y métodos) y crear múltiples instancias de objetos. Estándar de nombres es: sustantivos en minúsculas con 1ª en mayúscula. • Clases pueden ser: • Abstractas (no tienen instancias de objetos, ni métodos implantados en particular) • Instanciables (tienen objetos) • Sintaxis de clases: (solo 1 clase public por archivo .java con el mismo nombre del archivo! + debe tener 1 un método <public static void main (String args [ ]) { }> si es la clase que se va mandar a ejecutar al principio) <modificadores: public, private> <abstract> class <nombre-clase> extends <super-clase> implements <interface> { // atributos (e.g. data member, instance variable, data field) // constructor // métodos // // // } (e.g. un método especial para construir/inicializar un objeto nuevo, siempre public) (e.g función, procedimiento). Dos tipos de métodos indispensables son: setters (para asignar valores) y getters (para recuperar valores). los métodos de una sub-clase pueden <override> los de la superclase. al usar <super>.<metodo> se invoca el método de la super clase NOTAS: <super-clase> puede ser importada directamente vía <paquete>.<nombresuperclase> . Un paquete <package> es un grupo de clases + otros subpaquetes. RECORDAR: no herencia múltiple. Default es cuando no se pone un <modifier> e implica <private>. El alcance de acceso está basado en: <clase, paquete, subclase, universo: (public(4),protected(3),default(2), private(1)>, de izq->derecha. Una clase puede implantar 1 o varias interfaces. Notas de Java SE 2009 Dr. Manuel Mora T. 20/ 150 5. Definición de Clases y Objetos. • • ALCANCE DE <MODIFIERS> EN CLASES: • public La clase es accessable desde cualquier otra clase en mismo paquete u otro paquete. • private (o cuando no se usa <modifier> La clase es accessable solo por clases del mismo <package> ALCANCE DE <MODIFIERS> EN VAR-METODOS DE CLASES: • public una variable/método <public> en una clase puede ser accesada por cualquier clase del mismo <package>, o subclase en otro <package> o cualquier otra clase. • protected una variable/método <protected> en una clase puede ser accesada solo por clase del mismo <package>, o subclase en otro <package> o pero no por otras clases • <no modifier> una variable/método <sin modifier> en una clase puede ser accesada solo por clases del mismo <package> • private una variable/método <private> en una clase puede ser accesada solo la clase que declara esto (no por subclase) Access Levels Modifier Class Package Subclass World public Y Y Y Y protected Y Y Y N no modifier Y Y N N Y N N N private Notas de Java SE 2009 Dr. Manuel Mora T. 21/ 150 5. Definición de Clases y Objetos. • Pasos (pueden integrarse): • Declarar objeto: <Clase> <nombre-objeto>; • Crear instancia: <nombre-objeto> = new <Clase>(); • Inicializar: <nombre-objeto> = new <Clase>(parms); O: <Clase> <objeto> = new <Clase>(parms); • Para accesar atributos y métodos públicos (de instancias), usar: <objeto>.<atributo> o <objeto>.<método>(parms); • Para accesar atributos y métodos de una clase abstracta (un atributo o método de tipo <static>, usar: <clase>.<atributo> o <clase>.<método>(parms); • Es posible asignar un <objeto> a otro <objeto> simplemente usando: • <objeto1> = <objeto2>; Notas de Java SE 2009 Dr. Manuel Mora T. 22/ 150 5. Definición de Clases y Objetos. • Sintaxis de Atributos: // <public, protected, <no modifier>, private> <static> <Tipo> <nombre>, <otras atributos del mismo tipo>, …; // revisar definición de variables // usar keyword <this>.<atributo> para clarificar cual atributo está siendo usado (puede haber declaración doble de atributo y de parámetro en un constructor) • Sintaxis de Atributos: <static> Se usa <static> para definir VARIABLES DE CLASE. Una variable de este tipo es única para todos los objetos creados de dicha clase. Se accesan como <clase>.variable. Ejemplo de Tutorial SUN: public class Bicycle{ private int cadence; private int gear; private int speed; private int id; private static int numberOfBicycles = 0; public Bicycle(int startCadence, int startSpeed, int startGear){ gear = startGear; cadence = startCadence; speed = startSpeed; } } // increment number of Bicycles and assign ID number id = ++numberOfBicycles; // new method to return the ID instance variable public int getID() { return id; } ..... Notas de Java SE 2009 Dr. Manuel Mora T. 23/ 150 5. Definición de Clases y Objetos. • Sintaxis de Métodos: // <public, protected, <no modifier>, private> <static> <Tipo de retorno, puede ser void> <nombre>, ( <lista de parámetros>) { } // procedimiento sin parámetros void <nombre-método> () { } // procedimiento con parámetros void <nombre-método> ( <tipo> var1, <tipo> var2, ) { } // procedimiento con # de parámetros no especificado del mismo tipo (puede pasarse un arreglo o una lista de parámetros) void <nombre-método> ( <tipo>… <variable>) { } // procedimiento con parámetros variables del mismo tipo usando un arreglo (debe pasarse un arreglo) void <nombre-método> ( <tipo>[ ] <arreglo>) { } // función <tipo-retorno> <nombre-método> ( <tipo> var1, <tipo> var2, ) { return <valor-retorno>; } Class Methods The Java programming language supports static methods as well as static variables. Static methods, which have the static modifier in their declarations, should be invoked with the class name, without the need for creating an instance of the class, as in: ClassName.methodName(args) Notas de Java SE 2009 Dr. Manuel Mora T. 24/ 150 5. Definición de Clases y Objetos. • Sintaxis de Métodos: NOTA 0: solo existe el paso de parámetros x valor, no por referencia. Sin embargo, si se pasa un objeto, por default, esto es una referencia, y su contenido puede ser alterado en el método. NOTA 1: los métodos necesitan un modificador primero de entre: public, protected, <no modifier>, o <private> + <static si método de clase> NOTA 2: static se usa para métodos de clase (no de instancias / objetos ). NOTA 3: los métodos pueden ser sobrecargados (mismo nombre, diferentes parámetros). El compilador distingue el método correcto al analizar la secuencia y tipos de parámetros pasados al método. NOTA 4: las clases tienen un método o métodos especiales para inicializar la clase, llamados constructores (pero NO retornan valores NI son heredados), con la siguiente sintaxis: // constructor (el nombre del método debe ser el mismo que el de la clase) public <nombre-clase> ( <parms>) { } // si no hay un constructor, el default generado por el compilador es <nombreclase>(){ }, pero si se añade uno, este ya no existe y será un error al tratar de llamarlo. } } NOTA 5: estándar de nombres es verbos en minúsculas (e iniciando con minúscula) y en caso de ser varios verbos deben ir pegados con 1ª letra en mayúscula Notas de Java SE 2009 Dr. Manuel Mora T. 25/ 150 5. Definición de Clases y Objetos. • Clases Anidadas: Ejemplo de Tutorial Sun public class StackOfInts { private int[] stack; private int next = 0; // index of last item in stack + 1 public StackOfInts(int size) { //create an array large enough to hold the stack stack = new int[size]; } public void push(int on) { if (next < stack.length) stack[next++] = on; } public boolean isEmpty() { return (next == 0); } public int pop(){ if (!isEmpty()) return stack[--next]; // top item on stack else return 0; } public int getStackSize() { return next; } private class StepThrough { // start stepping through at i=0 private int i = 0; // increment index public void increment() { if ( i < stack.length) i++; } // retrieve current element public int current() { return stack[i]; } // last element on stack? public boolean isLast(){ if (i == getStackSize() - 1) return true; else return false; } } public StepThrough stepThrough() { return new StepThrough(); } public static void main(String[] args) { // instantiate outer class as "stackOne" StackOfInts stackOne = new StackOfInts(15); // populate stackOne for (int j = 0 ; j < 15 ; j++) { stackOne.push(2*j); } // instantiate inner class as "iterator" StepThrough iterator = stackOne.stepThrough(); // print out stackOne[i], one per line while(!iterator.isLast()) { System.out.print(iterator.current() + " "); iterator.increment(); } System.out.println(); } } Notas de Java SE 2009 Dr. Manuel Mora T. 26/ 150 5. Definición de Clases y Objetos. • Enum Types An enum type is a type whose fields consist of a fixed set of constants. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week. Because they are constants, the names of an enum type's fields are in uppercase letters. In the Java programming language, you define an enum type by using the enum keyword. For example, you would specify a days-of-the-week enum type as: public enum DayType { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY } DayType day; Notas de Java SE 2009 Dr. Manuel Mora T. 27/ 150 5. Definición de Clases y Objetos. • Enum Types Ejemplo de Tutorial Java Sun: public class EnumTest { Day day; public EnumTest(Day day) { this.day = day; } public void tellItLikeItIs() { switch (day) { bad."); case MONDAY: System.out.println("Mondays are break; case FRIDAY: System.out.println("Fridays are better."); break; case SATURDAY: case SUNDAY: System.out.println("Weekends are best."); break; default: so-so."); } System.out.println("Midweek days are break; } public static void main(String[] args) { EnumTest firstDay = new EnumTest(Day.MONDAY); firstDay.tellItLikeItIs(); EnumTest thirdDay = new EnumTest(Day.WEDNESDAY); thirdDay.tellItLikeItIs(); EnumTest fifthDay = new EnumTest(Day.FRIDAY); fifthDay.tellItLikeItIs(); EnumTest sixthDay = new EnumTest(Day.SATURDAY); sixthDay.tellItLikeItIs(); EnumTest seventhDay = new EnumTest(Day.SUNDAY); seventhDay.tellItLikeItIs(); } } Notas de Java SE 2009 Dr. Manuel Mora T. 28/ 150 5. Definición de Clases y Objetos. • Uso de Paquetes <packages> e Importaciones <import>: • Los paquetes son usados para agrupar clases (que el diseñador considera deben estar agrupadas por razones semánticas). Estándar de nombres son: sustantivos en minúsculas. • El conjunto de paquetes es organizado jerárquicamente (1 paquete principal, y sub-paquetes, … (como un directorio)). • La sintaxis, dentro del archivo fuente al declarar una clase, para indicar a que paquete pertenece es: …; package <nombre-paquete-top>.<sub.paquete>, • <import> sirve para indicar al compilador donde buscar clases que son usadas pero no definidas en el archivo fuente ni definidas en el mismo paquete al que pertenece las clases del archivo fuente. NOTA: debe quedar claro que existirá 1 declaración de <package> (a que paquete pertenecen las clases del archivo fuente), y 0, 1 o más declaraciones de <import>. • La sintaxis es: <import> <nombre de paquete>.<nombre de clase a importar>; <import> <nombre de paquete>.*; // para importar todas las clases de dicho paquete Notas de Java SE 2009 Dr. Manuel Mora T. 29/ 150 6. Organización de Proyectos en Java. • Proyectos en Java son organizados jerárquicamente: JavaProjects/ Project01/ src/ docs/ classes/ paqueteA paqueteB paqueteC paqueteTop/ paqueteA/ paqueteB/ paqueteC/ • Despliegue de Proyectos Java se realizan usualmente creando archivos ejecutables de tipo <jar>, siguiente el siguiente proceso: • • • Crear temporalArch que contenga: • Main-class: <paquete>.<clase principal> // donde está el método <main> Compilar con: • jar cmf temporalArch programa.jar Ejecutar con: • java -jar <directorio>/programa.jar Notas de Java SE 2009 Dr. Manuel Mora T. 30/ 150 6. Organización de Proyectos en Java. Ciclo de Desarrollo: • • • • • • + • • Captura de Requerimientos ( (lo que se necesita + lo que desea) de manera general) Análisis (lo que el sistema debe realizar detalladamente (en OOA: dominio de actores (objetos (físicos y/o conceptuales) + conductas propias + interaciones + actividades). Diseño (cómo finalmente el sistema implantará el modelo de análisis ). Desarrollo (construcción de objetos). Test (verificación de conductas e interacciones de objetos como un sistema). Implantación (liberación del sistema integrado). Mantenimiento (correcciones, adiciones, cambios al sistema). Retiro (eliminación del sistema). Notas de Java SE 2009 Dr. Manuel Mora T. 31/ 150 6. Organización de Proyectos en Java. Dado que Java es un lenguaje de tipo OOP, y OOP busca: •Reusabilidad •Extensibilidad •Flexibilidad Esperaríamos que Java proporcione capacidades para lograr esto. Esto es soportado vía: •Abstracción •Encapsulamiento •Herencia •Polimorfismo Notas de Java SE 2009 Dr. Manuel Mora T. 32/ 150 7. Números y Strings. The Java programming language supports basic arithmetic with its arithmetic operators: +, -, *, /, and %. The Math class in the java.lang package provides methods and constants for doing more advanced mathematical computation. The methods in the Math class are all static, so you call them directly from the class, like this: Math.cos(angle); -------------------------------------------------------------------------------Note : Using the static import language feature, you don't have to write Math in front of every math function: import static java.lang.Math.*; This allows you to invoke the Math class methods by their simple names. For example: cos(angle); -------------------------------------------------------------------------------Constants and Basic Methods The Math class includes two constants: Math.E, which is the base of natural logarithms, and Math.PI, which is the ratio of the circumference of a circle to its diameter Methods Implemented by all Subclasses of Number Method byte byteValue() short shortValue() int intValue() long longValue() float floatValue() double doubleValue() int compareTo(Byte anotherByte) int compareTo(Double anotherDouble) int compareTo(Float anotherFloat) int compareTo(Integer anotherInteger) int compareTo(Long anotherLong) int compareTo(Short anotherShort) boolean equals(Object obj) Notas de Java SE 2009 Description Converts the value of this Number object to the primitive data type returned. Compares this Number object to the argument. Determines whether this number object is equal to the argument. The methods return true if the argument is not null and is an object of the same type and with the same numeric value. There are some extra requirements for Double and Float objects that are described in the Java API documentation. Dr. Manuel Mora T. 33/ 150 7. Números y Strings. Methods Implemented by all Subclasses of Number Method Description static Integer decode(String s) Decodes a string into an integer. Can accept string representations of decimal, octal, or hexadecimal numbers as input. static int parseInt(String s) Returns an integer (decimal only). static int parseInt(String s, int radix) Returns an integer, given a string representation of decimal, binary, octal, or hexadecimal (radix equals 10, 2, 8, or 16 respectively) numbers as input. String toString() Returns a String object representing the value of this Integer. static String toString(int i) Returns a String object representing the specified integer. static Integer valueOf(int i) Returns an Integer object holding the value of the specified primitive. static Integer valueOf(String s) Returns an Integer object holding the value of the specified string representation. static Integer valueOf(String s, int radix) Returns an Integer object holding the integer value of the specified string representation, parsed with the value of radix. For example, if s = "333" and radix = 8, the method returns the base-ten integer equivalent of the octal number 333. Ejemplo de uso: String s=Integer.toString(valor); Converting Numbers to Strings Sometimes you need to convert a number to a string because you need to operate on the value in its string form. There are several easy ways to convert a number to a string: int i; String s1 = "" + i; //Concatenate "i" with an empty string; //conversion is handled for you. or String s2 = String.valueOf(i); //The valueOf class method. Each of the Number subclasses includes a class method, toString(), that will convert its primitive type to a string. For example: int i; double d; String s3 = Integer.toString(i); String s4 = Double.toString(d); Notas de Java SE 2009 Dr. Manuel Mora T. 34/ 150 7. Números y Strings. Basic Math Methods Method Description double abs(double d) float abs(float f) int abs(int i) long abs(long lng) Returns the absolute value of the argument. double ceil(double d) Returns the smallest integer that is greater than or equal to the argument. Returned as a double. double floor(double d) Returns the largest integer that is less than or equal to the argument. Returned as a double. double rint(double d) Returns the integer that is closest in value to the argument. Returned as a double. long round(double d) int round(float f) Returns the closest long or int, as indicated by the method's return type, to the argument. double min(double arg1, double arg2) float min(float arg1, float arg2) int min(int arg1, int arg2) long min(long arg1, long arg2) double max(double arg1, double arg2) float max(float arg1, float arg2) int max(int arg1, int arg2) long max(long arg1, long arg2) Returns the smaller of the two arguments. Returns the larger of the two arguments. Random Numbers The random() method returns a pseudo-randomly selected number between 0.0 and 1.0. The range includes 0.0 but not 1.0. In other words: 0.0 <= Math.random() < 1.0. To get a number in a different range, you can perform arithmetic on the value returned by the random method. For example, to generate an integer between 0 and 9, you would write: int number = (int)(Math.random() * 10); By multiplying the value by 10, the range of possible values becomes 0.0 <= number < 10.0. Using Math.random works well when you need to generate a single random number. If you need to generate a series of random numbers, you should create an instance of java.util.Random and invoke methods on that object to generate numbers Notas de Java SE 2009 Dr. Manuel Mora T. 35/ 150 7. Números y Strings. Exponential and Logarithmic Methods Method Description double exp(double d) Returns the base of the natural logarithms, e, to the power of the argument. double log(double d) Returns the natural logarithm of the argument. double pow(double base, double exponent) Returns the value of the first argument raised to the power of the second argument. double sqrt(double d) Returns the square root of the argument. Trigonometric Methods Method Description double sin(double d) Returns the sine of the specified double value. double cos(double d) Returns the cosine of the specified double value. double tan(double d) Returns the tangent of the specified double value. double asin(double d) Returns the arcsine of the specified double value. double acos(double d) Returns the arccosine of the specified double value. double atan(double d) Returns the arctangent of the specified double value. double atan2(double y, double x) Converts rectangular coordinates (x, y) to polar coordinate (r, theta) and returns theta. double toDegrees(double d) double toRadians(double d) Converts the argument to degrees or radians. Notas de Java SE 2009 Dr. Manuel Mora T. 36/ 150 7. Números y Strings. Impresión de números usando: %+Flags+Converter System.out.format(<pattern>, args) + import java.util.*; System.out.printf(<pattern>, args) + import java.util.*; Converter Flag Explanation %d A decimal integer. %f A float. %n A new line character appropriate to the platform running the application. You should always use %n, rather than \n. % tB A date & time conversion—locale-specific full name of month. % td, % te A date & time conversion—2-digit day of month. td has leading zeroes as needed, te does not. % ty, % tY A date & time conversion—ty = 2-digit year, tY = 4-digit year. % tl A date & time conversion—hour in 12-hour clock. % tM A date & time conversion—minutes in 2 digits, with leading zeroes as necessary. % tp A date & time conversion—locale-specific am/pm (lower case). % tm A date & time conversion—months in 2 digits, with leading zeroes as necessary. % tD A date & time conversion—date as %tm%td%ty 08 Eight characters in width, with leading zeroes as necessary. + Includes sign, whether positive or negative. , Includes locale-specific grouping characters. - Left-justified.. .3 Three places after decimal point. 10.3 Ten characters in width, right justified, with three places after decimal point. Notas de Java SE 2009 Dr. Manuel Mora T. 37/ 150 7. Números y Strings. Ejemplo: import java.util.*; public class TestFormat { public static void main(String[] args) { long n = 461012; System.out.format("%d%n", n); System.out.format("%08d%n", n); System.out.format("%+8d%n", n); System.out.format("%,8d%n", n); System.out.format("%+,8d%n%n", n); double pi = Math.PI; System.out.format("%f%n", pi); System.out.format("%.3f%n", pi); System.out.format("%10.3f%n", pi); System.out.format("%-10.3f%n", pi); System.out.format(Locale.FRANCE, "%-10.4f%n%n", pi); Calendar c = Calendar.getInstance(); System.out.format("%tB %te, %tY%n", c, c, c); System.out.format("%tl:%tM %tp%n", c, c, c); System.out.format("%tD%n", c); } } Notas de Java SE 2009 Dr. Manuel Mora T. 38/ 150 7. Números y Strings. The DecimalFormat Class You can use the java.text.DecimalFormat class to control the display of leading and trailing zeros, prefixes and suffixes, grouping (thousands) separators, and the decimal separator. DecimalFormat offers a great deal of flexibility in the formatting of numbers, but it can make your code more complex. The example that follows creates a DecimalFormat object, myFormatter, by passing a pattern string to the DecimalFormat constructor. The format() method, which DecimalFormat inherits from NumberFormat, is then invoked by myFormatter—it accepts a double value as an argument and returns the formatted number in a string: Here is a sample program that illustrates the use of DecimalFormat: import java.text.*; public class DecimalFormatDemo { static public void customFormat(String pattern, double value ) { DecimalFormat myFormatter = new DecimalFormat(pattern); String output = myFormatter.format(value); System.out.println(value + " " + pattern + " " + output); } static public void main(String[] args) { } } customFormat("###,###.###", 123456.789); customFormat("###.##", 123456.789); customFormat("000000.000", 123.78); customFormat("$###,###.###", 12345.67); The output is: 123456.789 ###,###.### 123,456.789 123456.789 ###.## 123456.79 123.78 000000.000 000123.780 12345.67 $###,###.### $12,345.67 Notas de Java SE 2009 Dr. Manuel Mora T. 39/ 150 7. Números y Strings. DecimalFormat.java Output Value 123456.789 Pattern ###,###.### Output Explanation 123,456.789 The pound sign (#) denotes a digit, the comma is a placeholder for the grouping separator, and the period is a placeholder for the decimal separator. 123456.789 ###.## 123456.79 123.78 000000.000 000123.780 12345.67 $###,###.### $12,345.67 The value has three digits to the right of the decimal point, but the pattern has only two. The format method handles this by rounding up. The pattern specifies leading and trailing zeros, because the 0 character is used instead of the pound sign (#). The first character in the pattern is the dollar sign ($). Note that it immediately precedes the leftmost digit in the formatted output. « Previous • Trail • Next » Notas de Java SE 2009 Dr. Manuel Mora T. 40/ 150 7. Números y Strings. Characters Most of the time, if you are using a single character value, you will use the primitive char type. For example: char ch = 'a'; char uniChar = '\u039A'; // Unicode for uppercase Greek omega character char[] charArray ={ 'a', 'b', 'c', 'd', 'e' }; // an array of chars There are times, however, when you need to use a char as an object—for example, as a method argument where an object is expected. The Java programming language provides a wrapper class that "wraps" the char in a Character object for this purpose. An object of type Character contains a single field, whose type is char. This Character class also offers a number of useful class (i.e., static) methods for manipulating characters. You can create a Character object with the Character constructor: Character ch = new Character('a'); The Java compiler will also create a Character object for you under some circumstances. For example, if you pass a primitive char into a method that expects an object, the compiler automatically converts the char to a Character for you. This feature is called autoboxing—or unboxing, if the conversion goes the other way. Here is an example of boxing, Character ch = 'a'; // the primitive char 'a' is boxed into the Character object ch and here is an example of both boxing and unboxing, Character test(Character c) {...} // method parameter and return type = Character object char c = test('x'); // primitive 'x' is boxed for method test, return is unboxed to char 'c' -------------------------------------------------------------------------------Note: The Character class is immutable, so that once it is created, a Character object cannot be changed. -------------------------------------------------------------------------------- Notas de Java SE 2009 Dr. Manuel Mora T. 41/ 150 7. Números y Strings. Useful Methods in the Character Class Method Description boolean isLetter(char ch) boolean isDigit(char ch) Determines whether the specified char value is a letter or a digit, respectively. boolean isWhiteSpace(char ch) Determines whether the specified char value is white space. boolean isUpperCase(char ch) boolean isLowerCase(char ch) Determines whether the specified char value is uppercase or lowercase, respectively. char toUpperCase(char ch) char toLowerCase(char ch) Returns the uppercase or lowercase form of the specified char value. toString(char ch) Returns a String object representing the specified character value—that is, a onecharacter string. Notas de Java SE 2009 Dr. Manuel Mora T. 42/ 150 7. Números y Strings. Escape Sequences A character preceded by a backslash (\) is an escape sequence and has special meaning to the compiler. The newline character (\n) has been used frequently in this tutorial in System.out.println() statements to advance to the next line after the string is printed. The following table shows the Java escape sequences: Escape Sequences Escape Sequence Description \t Insert a tab in the text at this point. \b Insert a backspace in the text at this point. \n Insert a newline in the text at this point. \r Insert a carriage return in the text at this point. \f Insert a formfeed in the text at this point. \' Insert a single quote character in the text at this point. \" Insert a double quote character in the text at this point. \\ Insert a backslash character in the text at this point. When an escape sequence is encountered in a print statement, the compiler interprets it accordingly. For example, if you want to put quotes within quotes you must use the escape sequence, \", on the interior quotes. To print the sentence She said "Hello!" to me. you would write System.out.println("She said \"Hello!\" to me."); Notas de Java SE 2009 Dr. Manuel Mora T. 43/ 150 7. Números y Strings. Methods in the String Class Method Description String substring(int beginIndex, int endIndex) Returns a new string that is a substring of this string. The first integer argument specifies the index of the first character. The second integer argument is the index of the last character + 1. String substring(int beginIndex) Returns a new string that is a substring of this string. The integer argument specifies the index of the first character. Here, the returned substring extends to the end of the original string. Method Description String[] split(String regex) String[] split(String regex, int limit) Searches for a match as specified by the string argument (which contains a regular expression) and splits this string into an array of strings accordingly. The optional integer argument specifies the maximum size of the returned array. Regular expressions are covered in the lesson titled "Regular Expressions." CharSequence subSequence(int beginIndex, int endIndex) Returns a new character sequence constructed from beginIndex index up until endIndex - 1. String trim() Returns a copy of this string with leading and trailing white space removed. String toLowerCase() String toUpperCase() Returns a copy of this string converted to lowercase or uppercase. If no conversions are necessary, these methods return the original string. Notas de Java SE 2009 Dr. Manuel Mora T. 44/ 150 7. Números y Strings. Methods in the String Class Method Description int indexOf(int ch) int lastIndexOf(int ch) Returns the index of the first (last) occurrence of the specified character. int indexOf(int ch, int fromIndex) int lastIndexOf(int ch, int fromIndex) Returns the index of the first (last) occurrence of the specified character, searching forward (backward) from the specified index. int indexOf(String str) int lastIndexOf(String str) Returns the index of the first (last) occurrence of the specified substring. int indexOf(String str, int fromIndex) int lastIndexOf(String str, int fromIndex) Returns the index of the first (last) occurrence of the specified substring, searching forward (backward) from the specified index. boolean contains(CharSequence s) Returns true if the string contains the specified character sequence. Method Description String replace(char oldChar, char newChar) Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar. String replace(CharSequence target, CharSequence replacement) Replaces each substring of this string that matches the literal target sequence with the specified literal replacement sequence. String replaceAll(String regex, String replacement) Replaces each substring of this string that matches the given regular expression with the given replacement. String replaceFirst(String regex, String replacement) Replaces the first substring of this string that matches the given regular expression with the given replacement. Notas de Java SE 2009 Dr. Manuel Mora T. 45/ 150 7. Números y Strings. Methods in the String Class Method boolean endsWith(String suffix) boolean startsWith(String prefix) Description Returns true if this string ends with or begins with the substring specified as an argument to the method. boolean startsWith(String prefix, int offset) Considers the string beginning at the index offset, and returns true if it begins with the substring specified as an argument. int compareTo(String anotherString) Compares two strings lexicographically. Returns an integer indicating whether this string is greater than (result is > 0), equal to (result is = 0), or less than (result is < 0) the argument. int compareToIgnoreCase(String str) Compares two strings lexicographically, ignoring differences in case. Returns an integer indicating whether this string is greater than (result is > 0), equal to (result is = 0), or less than (result is < 0) the argument. boolean equals(Object anObject) Returns true if and only if the argument is a String object that represents the same sequence of characters as this object. boolean equalsIgnoreCase(String anotherString) Returns true if and only if the argument is a String object that represents the same sequence of characters as this object, ignoring differences in case. boolean regionMatches(int toffset, String other, int ooffset, int len) Tests whether the specified region of this string matches the specified region of the String argument. Region is of length len and begins at the index toffset for this string and ooffset for the other string. boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) Tests whether the specified region of this string matches the specified region of the String argument. Region is of length len and begins at the index toffset for this string and ooffset for the other string. The boolean argument indicates whether case should be ignored; if true, case is ignored when comparing characters. boolean matches(String regex) Tests whether this string matches the specified regular expression. Regular expressions are discussed in the lesson titled "Regular Expressions." Notas de Java SE 2009 Dr. Manuel Mora T. 46/ 150 7. Números y Strings. The StringBuilder Class StringBuilder objects are like String objects, except that they can be modified. Internally, these objects are treated like variable-length arrays that contain a sequence of characters. At any point, the length and content of the sequence can be changed through method invocations. Strings should always be used unless string builders offer an advantage in terms of simpler code (see the sample program at the end of this section) or better performance. For example, if you need to concatenate a large number of strings, appending to a StringBuilder object is more efficient. Length and Capacity The StringBuilder class, like the String class, has a length() method that returns the length of the character sequence in the builder. Unlike strings, every string builder also has a capacity, the number of character spaces that have been allocated. The capacity, which is returned by the capacity() method, is always greater than or equal to the length (usually greater than) and will automatically expand as necessary to accommodate additions to the string builder. Constructor Description StringBuilder() Creates an empty string builder with a capacity of 16 (16 empty elements). StringBuilder(CharSequence cs) Constructs a string builder containing the same characters as the specified CharSequence, plus an extra 16 empty elements trailing the CharSequence. StringBuilder(int initCapacity) Creates an empty string builder with the specified initial capacity. StringBuilder(String s) Creates a string builder whose value is initialized by the specified string, plus an extra 16 empty elements trailing the string. For example, the following code StringBuilder sb = new StringBuilder(); // creates empty builder, capacity 16 sb.append("Greetings"); // adds 9 character string at beginning will produce a string builder with a length of 9 and a capacity of 16 Notas de Java SE 2009 Dr. Manuel Mora T. 47/ 150 7. Números y Strings. StringBuilder Methods Method void setLength(int newLength) void ensureCapacity(int minCapacity) StringBuilder append(boolean b) StringBuilder append(char c) StringBuilder append(char[] str) StringBuilder append(char[] str, int offset, int len) StringBuilder append(double d) StringBuilder append(float f) StringBuilder append(int i) StringBuilder append(long lng) StringBuilder append(Object obj) StringBuilder append(String s) StringBuilder delete(int start, int end) StringBuilder deleteCharAt(int index) StringBuilder insert(int offset, boolean b) StringBuilder insert(int offset, char c) StringBuilder insert(int offset, char[] str) StringBuilder insert(int index, char[] str, int offset, int len) StringBuilder insert(int offset, double d) StringBuilder insert(int offset, float f) StringBuilder insert(int offset, int i) StringBuilder insert(int offset, long lng) StringBuilder insert(int offset, Object obj) StringBuilder insert(int offset, String s) StringBuilder replace(int start, int end, String s) Description Sets the length of the character sequence. If newLength is less than length(), the last characters in the character sequence are truncated. If newLength is greater than length(), null characters are added at the end of the character sequence. Ensures that the capacity is at least equal to the specified minimum. Appends the argument to this string builder. The data is converted to a string before the append operation takes place. Deletes the specified character(s) in this string builder. Inserts the second argument into the string builder. The first integer argument indicates the index before which the data is to be inserted. The data is converted to a string before the insert operation takes place. Replaces the specified character(s) in this string builder. void setCharAt(int index, char c) StringBuilder reverse() Reverses the sequence of characters in this string builder. String toString() Returns a string that contains the character sequence in the builder. Notas de Java SE 2009 Dr. Manuel Mora T. 48/ 150 8. Interfaces Interfaces in Java In the Java programming language, an interface is a reference type, similar to a class, that can contain only constants, method signatures, and nested types. There are no method bodies. Interfaces cannot be instantiated—they can only be implemented by classes or extended by other interfaces. Extension is discussed later in this lesson. Defining an interface is similar to creating a new class: public interface OperateCar { // constant declarations, if any } // method signatures int turn(Direction direction, // An enum with values RIGHT, LEFT double radius, double startSpeed, double endSpeed); int changeLanes(Direction direction, double startSpeed, double endSpeed); int signalTurn(Direction direction, boolean signalOn); int getRadarFront(double distanceToCar, double speedOfCar); int getRadarRear(double distanceToCar, double speedOfCar); ...... // more method signatures Note that the method signatures have no braces and are terminated with a semicolon. To use an interface, you write a class that implements the interface. When an instantiable class implements an interface, it provides a method body for each of the methods declared in the interface. For example, public class OperateBMW760i implements OperateCar { } // the OperateCar method signatures, with implementation -// for example: int signalTurn(Direction direction, boolean signalOn) { //code to turn BMW's LEFT turn indicator lights on //code to turn BMW's LEFT turn indicator lights off //code to turn BMW's RIGHT turn indicator lights on //code to turn BMW's RIGHT turn indicator lights off } // other members, as needed -- for example, helper classes // not visible to clients of the interface In the robotic car example above, it is the automobile manufacturers who will implement the interface. Chevrolet's implementation will be substantially different from that of Toyota, of course, but both manufacturers will adhere to the same interface. The guidance manufacturers, who are the clients of the interface, will build systems that use GPS data on a car's location, digital street maps, and traffic data to drive the car. In so doing, the guidance systems will invoke the interface methods: turn, change lanes, brake, accelerate, and so forth Notas de Java SE 2009 Dr. Manuel Mora T. 49/ 150 8. Interfaces Interfaces and Multiple Inheritance Interfaces have another very important role in the Java programming language. Interfaces are not part of the class hierarchy, although they work in combination with classes. The Java programming language does not permit multiple inheritance (inheritance is discussed later in this lesson), but interfaces provide an alternative. In Java, a class can inherit from only one class but it can implement more than one interface. Therefore, objects can have multiple types: the type of their own class and the types of all the interfaces that they implement. This means that if a variable is declared to be the type of an interface, its value can reference any object that is instantiated from any class that implements the interface. This is discussed later in this lesson, in the section titled "Using an Interface as a Type." Interface IA Interface IB class B Implements IB subclass AA Notas de Java SE 2009 Interface IC Class A Implements IA, IB, IC public interface IA { int getA(); } public interface IB { int getB(); } public interface IC { int getC(); } public class A implements IA, IB, IC { // métodos de IA, IB, IC + otros posibles // métodos propios de clase A } public class AA extends A { } // … // objetoAA hereda estructura de class A y de // interfaces IA, IB, IC (herencia múltiple) AA objetoAA = new objetoAA(); Dr. Manuel Mora T. 50/ 150 8. Interfaces The Interface Declaration An interface declaration consists of modifiers, the keyword interface, the interface name, a comma-separated list of parent interfaces (if any), and the interface body. The public access specifier indicates that the interface can be used by any class in any package. If you do not specify that the interface is public, your interface will be accessible only to classes defined in the same package as the interface. An interface can extend other interfaces, just as a class can extend or subclass another class. However, whereas a class can extend only one other class, an interface can extend any number of interfaces. The interface declaration includes a comma-separated list of all the interfaces that it extends. The Interface Body The interface body contains method declarations for all the methods included in the interface. A method declaration within an interface is followed by a semicolon, but no braces, because an interface does not provide implementations for the methods declared within it. All methods declared in an interface are implicitly public, so the public modifier can be omitted. An interface can contain constant declarations in addition to method declarations. All constant values defined in an interface are implicitly public, static, and final. Once again, these modifiers can be omitted. Notas de Java SE 2009 Dr. Manuel Mora T. 51/ 150 8. Interfaces Using an Interface as a Type When you define a new interface, you are defining a new reference data type. You can use interface names anywhere you can use any other data type name. If you define a reference variable whose type is an interface, any object you assign to it must be an instance of a class that implements the interface. As an example, here is a method for finding the largest object in a pair of objects, for any objects that are instantiated from a class that implements Relatable: public interface Relatable { // this (object calling isLargerThan) and other must be instances of the same class // returns 1, 0, -1 if this is greater than, equal to, or less than other public int isLargerThan(Relatable other); } public Object findLargest(Object object1, Object object2) { Relatable obj1 = (Relatable)object1; // object1 debe ser de 1 clase que implementa Relatable Relatable obj2 = (Relatable)object2; // object2 debe ser de 1 clase que implementa Relatable if ( (obj1).isLargerThan(obj2) > 0) return object1; else return object2; } By casting object1 to a Relatable type, it can invoke the isLargerThan method. Notas de Java SE 2009 Dr. Manuel Mora T. 52/ 150 8. Interfaces Rewriting Interfaces Consider an interface that you have developed called DoIt: public interface DoIt { void doSomething(int i, double x); int doSomethingElse(String s); } Suppose that, at a later time, you want to add a third method to DoIt, so that the interface now becomes: public interface DoIt { void doSomething(int i, double x); int doSomethingElse(String s); boolean didItWork(int i, double x, String s); } If you make this change, all classes that implement the old DoIt interface will break because they don't implement the interface anymore. Programmers relying on this interface will protest loudly. Try to anticipate all uses for your interface and to specify it completely from the beginning. Given that this is often impossible, you may need to create more interfaces later. For example, you could create a DoItPlus interface that extends DoIt: public interface DoItPlus extends DoIt { boolean didItWork(int i, double x, String s); } Now users of your code can choose to continue to use the old interface or to upgrade to the new interface. IMPORTANTE NOTA: Question 4: Is the following interface valid? public interface Marker { } Answer 4: Yes. Methods are not required. Empty interfaces can be used as types and to mark classes without requiring any particular method implementations. For an example of a useful empty interface, see java.io.Serializable. Notas de Java SE 2009 Dr. Manuel Mora T. 53/ 150 9. Herencia entre Clases Casting Objects We have seen that an object is of the data type of the class from which it was instantiated. For example, if we write public MountainBike myBike = new MountainBike(); then myBike is of type MountainBike. MountainBike is descended from Bicycle and Object. Therefore, a MountainBike is a Bicycle and is also an Object, and it can be used wherever Bicycle or Object objects are called for. The reverse is not necessarily true: a Bicycle may be a MountainBike, but it isn't necessarily. Similarly, an Object may be a Bicycle or a MountainBike, but it isn't necessarily. Casting shows the use of an object of one type in place of another type, among the objects permitted by inheritance and implementations. For example, if we write Object obj = new MountainBike(); then obj is both an Object and a Mountainbike (until such time as obj is assigned another object that is not a Mountainbike). This is called implicit casting. If, on the other hand, we write MountainBike myBike = obj; we would get a compile-time error because obj is not known to the compiler to be a MountainBike. However, we can tell the compiler that we promise to assign a MountainBike to obj by explicit casting: MountainBike myBike = (MountainBike)obj; This cast inserts a runtime check that obj is assigned a MountainBike so that the compiler can safely assume that obj is a MountainBike. If obj is not a Mountainbike at runtime, an exception will be thrown. -------------------------------------------------------------------------------Note: You can make a logical test as to the type of a particular object using the instanceof operator. This can save you from a runtime error owing to an improper cast. For example: if (obj instanceof MountainBike) { MountainBike myBike = (MountainBike)obj; } Here the instanceof operator verifies that obj refers to a MountainBike so that we can make the cast with knowledge that there will be no runtime exception thrown. Notas de Java SE 2009 Dr. Manuel Mora T. 54/ 150 9. Herencia entre Clases Overriding and Hiding Methods Instance Methods An instance method in a subclass with the same signature (name, plus the number and the type of its parameters) and return type as an instance method in the superclass overrides the superclass's method. The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed. The overriding method has the same name, number and type of parameters, and return type as the method it overrides. An overriding method can also return a subtype of the type returned by the overridden method. This is called a covariant return type. When overriding a method, you might want to use the @Override annotation that instructs the compiler that you intend to override a method in the superclass. If, for some reason, the compiler detects that the method does not exist in one of the superclasses, it will generate an error. For more information on @Override, see Annotations. Class Methods If a subclass defines a class method with the same signature as a class method in the superclass, the method in the subclass hides the one in the superclass. The distinction between hiding and overriding has important implications. The version of the overridden method that gets invoked is the one in the subclass. The version of the hidden method that gets invoked depends on whether it is invoked from the superclass or the subclass. Let's look at an example that contains two classes. The first is Animal, which contains one instance method and one class method: public class Animal { public static void testClassMethod() { System.out.println("The class method in Animal."); } public void testInstanceMethod() { System.out.println("The instance method in Animal."); } } The second class, a subclass of Animal, is called Cat: public class Cat extends Animal { public static void testClassMethod() { System.out.println("The class method in Cat."); } public void testInstanceMethod() { System.out.println("The instance method in Cat."); } public static void main(String[] args) { Cat myCat = new Cat(); Animal myAnimal = myCat; Animal.testClassMethod(); myAnimal.testInstanceMethod(); } } The Cat class overrides the instance method in Animal and hides the class method in Animal. The main method in this class creates an instance of Cat and calls testClassMethod() on the class and testInstanceMethod() on the instance. The output from this program is as follows: The class method in Animal. The instance method in Cat. As promised, the version of the hidden method that gets invoked is the one in the superclass, and the version of the overridden method that gets invoked is the one in the subclass. Notas de Java SE 2009 Dr. Manuel Mora T. 55/ 150 9. Herencia entre Clases Writing Final Classes and Methods You can declare some or all of a class's methods final. You use the final keyword in a method declaration to indicate that the method cannot be overridden by subclasses. The Object class does this—a number of its methods are final. You might wish to make a method final if it has an implementation that should not be changed and it is critical to the consistent state of the object. For example, you might want to make the getFirstPlayer method in this ChessAlgorithm class final: class ChessAlgorithm { enum ChessPlayer { WHITE, BLACK } ... final ChessPlayer getFirstPlayer() { return ChessPlayer.WHITE; } ... } Methods called from constructors should generally be declared final. If a constructor calls a non-final method, a subclass may redefine that method with surprising or undesirable results. Note that you can also declare an entire class final — this prevents the class from being subclassed . This is particularly useful, for example, when creating an immutable class like the String class Subclass Constructors The following example illustrates how to use the super keyword to invoke a superclass's constructor. Recall from the Bicycle example that MountainBike is a subclass of Bicycle. Here is the MountainBike (subclass) constructor that calls the superclass constructor and then adds initialization code of its own: public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear) { super(startCadence, startSpeed, startGear); seatHeight = startHeight; } Invocation of a superclass constructor must be the first line in the subclass constructor. The syntax for calling a superclass constructor is super(); --or-super(parameter list); With super(), the superclass no-argument constructor is called. With super(parameter list), the superclass constructor with a matching parameter list is called. Note: If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the noargument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem. Notas de Java SE 2009 Dr. Manuel Mora T. 56/ 150 9. Herencia entre Clases Abstract Methods and Classes An abstract class is a class that is declared abstract—it may or may not include abstract methods. Abstract classes cannot be instantiated, but they can be subclassed. An abstract method is a method that is declared without an implementation (without braces, and followed by a semicolon), like this: abstract void moveTo(double deltaX, double deltaY); If a class includes abstract methods, the class itself must be declared abstract, as in: public abstract class GraphicObject { // declare fields // declare non-abstract methods abstract void draw(); } When an abstract class is subclassed, the subclass usually provides implementations for all of the abstract methods in its parent class. However, if it does not, the subclass must also be declared abstract. -------------------------------------------------------------------------------Note: All of the methods in an interface (see the Interfaces section) are implicitly abstract, so the abstract modifier is not used with interface methods (it could be—it's just not necessary). -------------------------------------------------------------------------------- Abstract Classes versus Interfaces they can contain implemented methods. Such abstract classes are similar to interfaces, except that they provide a partial implementation, leaving it to subclasses to complete the implementation. If an abstract class contains only abstract method declarations, it should be declared as an interface instead. Unlike interfaces, abstract classes can contain fields that are not static and final, and Multiple interfaces can be implemented by classes anywhere in the class hierarchy, whether or not they are related to one another in any way. Think of Comparable or Cloneable, for example. By comparison, abstract classes are most commonly subclassed to share pieces of implementation. A single abstract class is subclassed by similar classes that have a lot in common (the implemented parts of the abstract class), but also have some differences (the abstract methods). Notas de Java SE 2009 Dr. Manuel Mora T. 57/ 150 9. Herencia entre Clases Object as a Superclass The Object class, in the java.lang package, sits at the top of the class hierarchy tree. Every class is a descendant, direct or indirect, of the Object class. Every class you use or write inherits the instance methods of Object. You need not use any of these methods, but, if you choose to do so, you may need to override them with code that is specific to your class. The methods inherited from Object that are discussed in this section are: protected Object clone() throws CloneNotSupportedException Creates and returns a copy of this object. public boolean equals(Object obj) Indicates whether some other object is "equal to" this one. protected void finalize() throws Throwable Called by the garbage collector on an object when garbage collection determines that there are no more references to the object public final Class getClass() Returns the runtime class of an object. public int hashCode() Returns a hash code value for the object. public String toString() Returns a string representation of the object. The equals() Method The equals() method compares two objects for equality and returns true if they are equal. The equals() method provided in the Object class uses the identity operator (==) to determine whether two objects are equal. For primitive data types, this gives the correct result. For objects, however, it does not. The equals() method provided by Object tests whether the object references are equal—that is, if the objects compared are the exact same object. To test whether two objects are equal in the sense of equivalency (containing the same information), you must override the equals() method. Here is an example of a Book class that overrides equals(): public class Book { ... public boolean equals(Object obj) { if (obj instanceof Book) return ISBN.equals((Book)obj.getISBN()); else return false; } } Book firstBook = new Book("0201914670"); //Swing Tutorial, 2nd edition Book secondBook = new Book("0201914670"); if (firstBook.equals(secondBook)) { System.out.println("objects are equal"); } else { System.out.println("objects are not equal"); } This program displays objects are equal even though firstBook and secondBook reference two distinct objects. They are considered equal because the objects compared contain the same ISBN number. You should always override the equals() method if the identity operator is not appropriate for your class. Notas de Java SE 2009 Dr. Manuel Mora T. 58/ 150 10. Flujos de E/S I/O Streams •Bytes •Byte Streams handle I/O of raw binary data. FileInputStream, FileOutputStream. • Buffered Streams optimize input and output by reducing the number of calls to the native API byte: BufferedInputStream, BufferedOutputStream; •Characters •Character Streams handle I/O of character data, automatically handling translation to and from the local character set FileReader, FileWriter • Buffered Streams optimize input and output by reducing the number of calls to the native API character: BufferedReader, BufferedWriter • Scanning and Formatting allows a program to read and write formatted text Scanner, System.out.print(), System.out.println(), System.out.format() •I/O from the Command Line describes the Standard Streams and the Console object System.out, System.in, System.err, System.console •Data & Objects •Data Streams handle binary I/O of primitive data type and String values DataInputStream, DataOutputStream •Object Streams handle binary I/O of objects ObjectInputStream, ObjectOutputStream •File I/O •File Objects help you to write platform-independent code that examines and manipulates files File •Random Access Files handle non-sequential file access RandomAccessFile Notas de Java SE 2009 Dr. Manuel Mora T. 59/ 150 10. Flujos de E/S I/O Streams •Byte Streams handle I/O of raw binary data. FileInputStream, FileOutputStream. // package Import java.io*; // declaración de flujos FileInputStream <fileIn> = null; FileOutputStream <fileOut> = null; byte <varByte> ; // creación de flujos <fileIn> = new FileInputStream(“nombreArchivoIn.txt”); <fileOut> = new FileOutputStream(“nombreArchivoOut.txt”); // métodos r/w <varByte> = (byte) <fileIn>.read(); // read() retorna un int <fileOut>.write(<varByte>); // cierre de fujos <fileIn>.close(); <fileOut>.close(); // código para detectar excepción de IO try { } catch (IOException e) { } import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class CopyBytes { public static void main(String[] args) throws IOException { FileInputStream in = null; FileOutputStream out = null; try { in = new FileInputStream("xanadu.txt"); out = new FileOutputStream("outagain.txt"); int c; while ((c = in.read()) != -1) { out.write(c); } } finally { if (in != null) { in.close(); } if (out != null) { out.close(); } } } } // usar c como int permite verificar EOF con valor -1. Notas de Java SE 2009 Dr. Manuel Mora T. 60/ 150 10. Flujos de E/S I/O Streams Character Streams handle I/O of character data, automatically handling translation to and from the local character set FileReader, FileWriter // package Import java.io*; // declaración de flujos FileReader<fileIn> = null; FileWriter <fileOut> = null; char <varChar> ; // creación de flujos <fileIn> = new FileReader(“nombreArchivoIn.txt”); <fileOut> = new FileWriter(“nombreArchivoOut.txt”); // métodos r/w <varChar> = (char) <fileIn>.read(); // read() retorna un int <fileOut>.write(<varChar>); // cierre de fujos <fileIn>.close(); <fileOut>.close(); // código para detectar excepción de IO try { } catch (IOException e) { } import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class CopyCharacters { public static void main(String[] args) throws IOException { FileReader inputStream = null; FileWriter outputStream = null; try { inputStream = new FileReader("xanadu.txt"); outputStream = new FileWriter("characteroutput.txt"); int c; while ((c = inputStream.read()) != -1) { outputStream.write(c); } finally { if (inputStream != null) { inputStream.close(); } if (outputStream != null) { outputStream.close(); } } } } // usar c como int permite verificar EOF con valor -1. Notas de Java SE 2009 Dr. Manuel Mora T. } 61/ 150 10. Flujos de E/S I/O Streams Buffered Streams optimize input and output by reducing the number of calls to the native API (necesitan usar internamente un flujo no buffered) byte: BufferedInputStream, BufferedOutputStream; character: BufferedReader, BufferedWriter, PrinterStream ->bytes, PrintWriter ->caracter // package Import java.io*; // declaración de flujos BufferedReader <fileIn> = null; PrintWriter <fileOut> = null; String <varString> ; // creación de flujos buffered incluyendo flujos internos <fileIn> = new BufferedReader( new FileReader(“nombreArchivoIn.txt”) ); <fileOut> = new PrinterWriter( new FileWriter(“nombreArchivoOut.txt”) ); // métodos r/w <varString> = <fileIn>.readln(); <fileOut>.println(<varByte>); // cierre de fujos <fileIn>.close(); <fileOut>.close(); import java.io.*; public class CopyLines { public static void main(String[] args) throws IOException { BufferedReader inputStream = null; PrintWriter outputStream = null; try { inputStream = new BufferedReader(new FileReader("xanadu.txt")); outputStream = new PrintWriter(new FileWriter("characteroutput.txt")); String l; while ((l = inputStream.readLine()) != null) { outputStream.println(l); } finally { if (inputStream != null) { inputStream.close(); } if (outputStream != null) { outputStream.close(); } } } } // EOF se checa con readline()=null Notas de Java SE 2009 Dr. Manuel Mora T. } 62/ 150 10. Flujos de E/S I/O Streams Scanning and Formatting allows a program to read and write formatted text. Usan un buffered flujo Scanner, System.out.print(), System.out.println(), System.out.format() Scanner <objeto> = null; Scanner <objeto> = new Scanner( <parametro> ) ; // <objeto>.hasNext() true si hay otro dato en el flujo asignado a <objeto> // <objeto>.hasNextInt() true sisiguiente dato es Int … // <objeto>.next() retorna siguiente valor como String // <objeto>.nextInt() retorna siguiente valor como Int // <objeto>.nextDouble() retorna siguiente valor como Double // <objeto>.nextBoolean() retorna siguiente valor como Boolean // <objeto>.nextByte() retorna siguiente valor como Byte // <objeto>.nextFloat() retorna siguiente valor como Float // <objeto>.useLocale(new Locale(“en”,”US”)) para indicar formato internacional // <objeto>.useDelimiter(<patron>) define patrón de delimitadores “\\s*” 1 o varios espacios en blanco o tabs o CRs “,\\s*” coma seguido de 1 o varios espacios en blanco // EJEMPLO: import java.io.*; import java.util.Scanner; public class ScanXan { public static void main(String[] args) throws IOException { Scanner s = null; try { s = new Scanner(new BufferedReader(new FileReader("xanadu.txt"))); while (s.hasNext()) { System.out.println(s.next()); } } finally { if (s != null) { s.close(); } } } } // EOF se checa con hasNext()=false Notas de Java SE 2009 Dr. Manuel Mora T. 63/ 150 10. Flujos de E/S // EJEMPLO: /* archivo: usnumbers.txt 8.5 32,767 3.14159 1,000,000.1 */ import java.io.FileReader; import java.io.BufferedReader; import java.io.IOException; import java.util.Scanner; import java.util.Locale; public class ScanSum { public static void main(String[] args) throws IOException { Scanner s = null; double sum = 0; try { s = new Scanner(new BufferedReader(new FileReader("usnumbers.txt"))); s.useLocale(Locale.US); while (s.hasNext()) { if (s.hasNextDouble()) { sum += s.nextDouble(); } else { s.next(); } } } finally { s.close(); } System.out.println(sum); } } Notas de Java SE 2009 Dr. Manuel Mora T. 64/ 150 10. Flujos de E/S The print and println Methods Invoking print or println outputs a single value after converting the value using the appropriate toString method. We can see this in the Root example: public class Root { public static void main(String[] args) { int i = 2; double r = Math.sqrt(i); System.out.print("The square root of "); System.out.print(i); System.out.print(" is "); System.out.print(r); System.out.println("."); i = 5; r = Math.sqrt(i); System.out.println("The square root of " + i + " is " + r + "."); // conversión de i y r a string automáticamente } } Here is the output of Root: The square root of 2 is 1.4142135623730951. The square root of 5 is 2.23606797749979 Notas de Java SE 2009 Dr. Manuel Mora T. 65/ 150 10. Flujos de E/S The format Method }The format method formats multiple arguments based on a format string. The format string consists of static text embedded with format specifiers; except for the format specifiers, the format string is output unchanged. Format strings support many features. In this tutorial, we'll just cover some basics. For a complete description, see format string syntax in the API specification. The Root2 example formats two values with a single format invocation: public class Root2 { public static void main(String[] args) { int i = 2; double r = Math.sqrt(i); System.out.format("The square root of %d is %f.%n", i, r); } } Here is the output: The square root of 2 is 1.414214. System.out.format("%f, %1$+020.10f %n", Math.PI); } Here's the output: 3.141593, +00000003.1415926536 } The elements must appear in the order shown. Working from the right, the optional elements are: •Precision. For floating point values, this is the mathematical precision of the formatted value. For s and other general conversions, this is the maximum width of the formatted value; the value is right-truncated if necessary. •Width. The minimum width of the formatted value; the value is padded if necessary. By default the value is left-padded with blanks. •Flags specify additional formatting options. In the Format example, the + flag specifies that the number should always be formatted with a sign, and the 0 flag specifies that 0 is the padding character. Other flags include - (pad on the right) and , (format number with locale-specific thousands separators). Note that some flags cannot be used with certain other flags or with certain conversions. •The Argument Index allows you to explicitly match a designated argument. You can also specify < to match the same argument as the previous specifier. Thus the example could have said: System.out.format("%f, %<+020.10f %n", Math.PI); Notas de Java SE 2009 Dr. Manuel Mora T. 66/ 150 10. Flujos de E/S I/O Streams •I/O from the Command Line describes the Standard Streams and the Console object System.out, System.in, System.err, System.console // package Import java.io*; // declaración de flujos Console <varConsole> = System.console(); // métodos r/w String <varString> = <varConsole>.readLine(<prompt>); char[] <varAChar> = <varConsole>.readPassword( <prompt> ); <varConsole>.format( <patron>, <vars> ); The Console A more advanced alternative to the Standard Streams is the Console. This is a single, predefined object of type Console that has most of the features provided by the Standard Streams, and others besides. The Console is particularly useful for secure password entry. The Console object also provides input and output streams that are true character streams, through its reader and writer methods. Before a program can use the Console, it must attempt to retrieve the Console object by invoking System.console(). If the Console object is available, this method returns it. If System.console returns NULL, then Console operations are not permitted, either because the OS doesn't support them or because the program was launched in a noninteractive environment. The Console object supports secure password entry through its readPassword method. This method helps secure password entry in two ways. First, it suppresses echoing, so the password is not visible on the user's screen. Second, readPassword returns a character array, not a String, so the password can be overwritten, removing it from memory as soon as it is no longer needed. Notas de Java SE 2009 Dr. Manuel Mora T. 67/ 150 10. Flujos de E/S I/O Streams •I/O from the Command Line describes the Standard Streams and the Console object System.out, System.in, System.err, System.console // package Import java.io*; // declaración de flujos Console <varConsole> = System.console(); // métodos r/w String <varString> = <varConsole>.readLine(<prompt>); char[] <varAChar> = <varConsole>.readPassword( <prompt> ); <varConsole>.format( <patron>, <vars> ); import java.io.Console; import java.util.Arrays; import java.io.IOException; public class Password { public static void main (String args[]) throws IOException { Console c = System.console(); if (c == null) { System.err.println("No console."); System.exit(1); } String login = c.readLine("Enter your login: "); char [] oldPassword = c.readPassword("Enter your old password: "); if (verify(login, oldPassword)) { boolean noMatch; do { char [] newPassword1 = c.readPassword("Enter your new password: "); char [] newPassword2 = c.readPassword("Enter new password again: "); noMatch = ! Arrays.equals(newPassword1, newPassword2); if (noMatch) { c.format("Passwords don't match. Try again.%n"); } else { change(login, newPassword1); c.format("Password for %s changed.%n", login); } Arrays.fill(newPassword1, ' '); Arrays.fill(newPassword2, ' '); } while (noMatch); } Arrays.fill(oldPassword, ' '); } //Dummy verify method. static boolean verify(String login, char[] password) { return true; //Dummy change method. static void change(String login, char[] password) {} } Notas de Java SE 2009 } Dr. Manuel Mora T. 68/ 150 10. Flujos de E/S I/O Streams •Data Streams handle binary I/O of primitive data type and String values DataInputStream, DataOutputStream // package Import java.io*; // declaración de flujos DataInputStream <fileIn> = null; DataOutputStream <fileOut> = null; // creación de flujos buffered incluyendo flujos internos <fileIn> = new DataInputStream ( new BufferedInputStream( new FileInputStream(“nombreArchivoIn.dat”) )); <fileOut> = new DataOutputStream ( new BufferedOutputStream( new FileOutputStream(“nombreArchivoOut.dat”) )); // métodos r/w <varInt> = <fileIn>.readInt(); <varDouble> = <fileIn>.readDouble(); <varString> = <fileIn>.readUTF(); // read para strings <fileOut>.writeInt( <varInt> ); <fileOut>.writeDouble( <varDouble> ); <fileOut>.writeUTF( <varUTF> ); // cierre de fujos <fileIn>.close(); <fileOut>.close(); Data streams support binary I/O of primitive data type values (boolean, char, byte, short, int, long, float, and double) as well as String values. All data streams implement either the DataInput interface or the DataOutput interface. This section focuses on the most widely-used implementations of these interfaces, DataInputStream and DataOutputStream. The DataStreams example demonstrates data streams by writing out a set of data records, and then reading them in again. Each record consists of three values related to an item on an invoice, as shown in the following table: Notas de Java SE 2009 Dr. Manuel Mora T. 69/ 150 10. Flujos de E/S static final String dataFile = "invoicedata"; static final double[] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 }; static final int[] units = { 12, 8, 13, 29, 50 }; static final String[] descs = { "Java T-shirt", "Java Mug", "Duke Juggling Dolls", "Java Pin", "Java Key Chain" }; out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(dataFile))); //DataStreams writes out the records and closes the output stream. for (int i = 0; i < prices.length; i ++) { out.writeDouble(prices[i]); out.writeInt(units[i]); out.writeUTF(descs[i]); } out.close(); in = new DataInputStream(new BufferedInputStream(new FileInputStream(dataFile))); double price; int unit; String desc; double total = 0.0; try { while (true) { price = in.readDouble(); unit = in.readInt(); desc = in.readUTF(); System.out.format("You ordered %d units of %s at $%.2f%n", unit, desc, price); total += unit * price; } } catch (EOFException e) { in.close(); } // fin de archivo es detectado con EOFException Notas de Java SE 2009 Dr. Manuel Mora T. 70/ 150 10. Flujos de E/S I/O Streams •Data Object Streams handle binary I/O of objects ObjectInputStream, ObjectOutputStream // package Import java.io*; // declaración de flujos ObjectInputStream <fileIn> = null; ObjectOutputStream <fileOut> = null; // creación de flujos buffered incluyendo flujos internos <fileIn> = new ObjectInputStream ( new BufferedInputStream( new FileInputStream(“nombreArchivoIn.dat”) )); <fileOut> = new ObjectOutputStream ( new BufferedOutputStream( new FileOutputStream(“nombreArchivoOut.dat”) )); // métodos r/w <varInt> = <fileIn>.readInt(); <varDouble> = <fileIn>.readDouble(); <varString> = <fileIn>.readUTF(); // read para strings <varObject> = (<class>) <fileIn>.readObject(); <fileOut>.writeInt( <varInt> ); <fileOut>.writeDouble( <varDouble> ); <fileOut>.writeUTF( <varUTF> ); <fileOut>.writeObject( <varObject>); // cierre de fujos <fileIn>.close(); <fileOut>.close(); Just as data streams support I/O of primitive data types, object streams support I/O of objects. Most, but not all, standard classes support serialization of their objects. Those that do implement the marker interface Serializable. The object stream classes are ObjectInputStream and ObjectOutputStream. These classes implement ObjectInput and ObjectOutput, which are subinterfaces of DataInput and DataOutput. That means that all the primitive data I/O methods covered in Data Streams are also implemented in object streams. So an object stream can contain a mixture of primitive and object values. The ObjectStreams example illustrates this. ObjectStreams creates the same application as DataStreams, with a couple of changes. First, prices are now BigDecimalobjects, to better represent fractional values. Second, a Calendar object is written to the data file, indicating an invoice date. If readObject() doesn't return the object type expected, attempting to cast it to the correct type may throw a ClassNotFoundException. In this simple example, that can't happen, so we don't try to catch the exception. Instead, we notify the compiler that we're aware of the issue by adding ClassNotFoundException to the main method's throws clause. Notas de Java SE 2009 Dr. Manuel Mora T. 71/ 150 10. Flujos de E/S import java.io.*; import java.math.BigDecimal; import java.util.Calendar; public class ObjectStreams { static final String dataFile = "invoicedata"; static final BigDecimal[] prices = { new BigDecimal("19.99"), new BigDecimal("9.99"), new BigDecimal("15.99"), new BigDecimal("3.99"), new BigDecimal("4.99") }; static final int[] units = { 12, 8, 13, 29, 50 }; static final String[] descs = { "Java T-shirt", "Java Mug", "Duke Juggling Dolls", "Java Pin", "Java Key Chain" }; public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectOutputStream out = null; try { out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(dataFile))); out.writeObject(Calendar.getInstance()); for (int i = 0; i < prices.length; i ++) { out.writeObject(prices[i]); out.writeInt(units[i]); out.writeUTF(descs[i]); } } finally { out.close(); } ObjectInputStream in = null; try { in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(dataFile))); Calendar date = null; BigDecimal price; int unit; String desc; BigDecimal total = new BigDecimal(0); date = (Calendar) in.readObject(); System.out.format ("On %tA, %<tB %<te, %<tY:%n", date); try { while (true) { price = (BigDecimal) in.readObject(); unit = in.readInt(); desc = in.readUTF(); System.out.format("You ordered %d units of %s at $%.2f%n", unit, desc, price); total = total.add(price.multiply(new BigDecimal(unit))); } } catch (EOFException e) {} System.out.format("For a TOTAL of: $%.2f%n", total); } finally { in.close(); } } } Notas de Java SE 2009 Dr. Manuel Mora T. 72/ 150 11. Excepciones • An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions. •When an error occurs within a method, the method creates an object and hands it off to the runtime system. The object, called an exception object, contains information about the error, including its type and the state of the program when the error occurred. •Creating an exception object and handing it to the runtime system is called throwing an exception. The exception handler chosen is said to catch the exception. •Grouping and Differentiating Error Types •Three types of exceptions: checked exceptions, errors, and runtime errors. Diferencias de Códigos para Manejo de Errores errorCodeType readFile { initialize errorCode = 0; open the file; if (theFileIsOpen) { determine the length of the file; if (gotTheFileLength) { allocate that much memory; if (gotEnoughMemory) { read the file into memory; if (readFailed) { errorCode = -1; } } else { errorCode = -2; } } else { errorCode = -3; } close the file; if (theFileDidntClose && errorCode == 0) { errorCode = -4; } else { errorCode = errorCode and -4; } } else { errorCode = -5; } return errorCode; readFile { try { open the file; determine its size; allocate that much memory; read the file into memory; close the file; } catch (fileOpenFailed) { doSomething; } catch (sizeDeterminationFailed) { doSomething; } catch (memoryAllocationFailed) { doSomething; } catch (readFailed) { doSomething; } catch (fileCloseFailed) { doSomething; } } } Notas de Java SE 2009 Dr. Manuel Mora T. 73/ 150 11. Excepciones // Estructura para manejo de excepciones try { // código normal } catch (<ExceptionType> <objExcepcion>) { // código para manejar excepción1 } catch (<ExceptionType> <objExcepcion>) { // código para manejar excepción2 } … finally { // código final siempre ejecutado aún cuando no haya excepciones } // intrucciones throw <exceptionObject>( <parametros>); Throw new <exceptionObject> (<parametros>); <objExcepción>.getMessage() // Es necesario definir en el método que tipos de excepciones se manejarán <modifiers> <nombreMetodo> throws <TipoExcepcion>, <TipoExcepcion>, { } // tipos usuales: Exception, ArithmeticException, FileNotFoundException, IOException Notas de Java SE 2009 Dr. Manuel Mora T. 74/ 150 12. Genéricos // Tipos Genéricos permiten definir una clase o métodos con tipo de parámetros // instanciados hasta que se declaran los objetos de dicha clase <modifiers> class <nombreClase>< A,B, > { } <modifiers> < A,B, > <tipo> <nombreMetodo> ( <parametros> ){ } // donde A, B, son los tipos genéricos definidos. Los códigos posibles, pero solo 1 de // cada uno, son los siguientes: E - Element (used extensively by the Java Collections Framework) K - Key N - Number T - Type V - Value S,U,V etc. - 2nd, 3rd, 4th types /** * Generic version of the Box class. */ public class Box<T> { public <U> void inspect(U u) { System.out.println("T: " + t.getClass().getName()); System.out.println("U: " + u.getClass().getName()); } private T t; // T stands for "Type" public void add(T t) { this.t = t; } } public T get() { return t; } Notas de Java SE 2009 Dr. Manuel Mora T. 75/ 150 12. Genéricos public class Box<T> { private T t; // T stands for "Type" public void add(T t) { this.t = t; public T get() { return t; } } } Box<Integer> integerBox; integerBox = new Box<Integer>(); // Box<Integer> integerBox = new Box<Integer>(); public class BoxDemo3 { public static void main(String[] args) { Box<Integer> integerBox = new Box<Integer>(); integerBox.add(new Integer(10)); Integer someInteger = integerBox.get(); // no cast! System.out.println(someInteger); } } ** * This version introduces a generic method. */ public class Box<T> { private T t; public void add(T t) { this.t = t; } public T get() { return t; } public <U> void inspect(U u){ System.out.println("T: " + t.getClass().getName()); System.out.println("U: " + u.getClass().getName()); } public static void main(String[] args) { Box<Integer> integerBox = new Box<Integer>(); integerBox.add(new Integer(10)); integerBox.inspect("some text"); } } Notas de Java SE 2009 Dr. Manuel Mora T. 76/ 150 12. Genéricos Bounded Type Parameters There may be times when you'll want to restrict the kinds of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for. To declare a bounded type parameter, list the type parameter's name, followed by the extends keyword, followed by its upper bound, which in this example is Number. Note that, in this context, extends is used in a general sense to mean either "extends" (as in classes) or "implements" (as in interfaces). /** * This version introduces a bounded type parameter. */ public class Box<T> { private T t; public void add(T t) { this.t = t; } public T get() { return t; } public <U extends Number> void inspect(U u){ System.out.println("T: " + t.getClass().getName()); System.out.println("U: " + u.getClass().getName()); } public static void main(String[] args) { Box<Integer> integerBox = new Box<Integer>(); integerBox.add(new Integer(10)); integerBox.inspect("some text"); // error: this is still String! } } Notas de Java SE 2009 Dr. Manuel Mora T. 77/ 150 12. Genéricos Subtyping Now consider the following method: public void boxTest(Box<Number> n){ // method body omitted } What type of argument does it accept? By looking at its signature, we can see that it accepts a single argument whose type is Box<Number>. But what exactly does that mean? Are you allowed to pass in Box<Integer> or Box<Double>, as you might expect? Surprisingly, the answer is "no", because Box<Integer> and Box<Double> are not subtypes of Box<Number>. Understanding why becomes much easier if you think of tangible objects — things you can actually picture — such as a cage: // A cage is a collection of things, with bars to keep them in. interface Cage<E> extends Collection<E>; -------------------------------------------------------------------------------Note: The Collection interface is the root interface of the collection hierarchy; it represents a group of objects. Since a cage would be used for holding a collection of objects (the animals), it makes sense to include it in this example. -------------------------------------------------------------------------------- Notas de Java SE 2009 Dr. Manuel Mora T. 78/ 150 12. Genéricos Wildcards Earlier we mentioned that English is ambiguous. The phrase "animal cage" can reasonably mean "all-animal cage", but it also suggests an entirely different concept: a cage designed not for any kind of animal, but rather for some kind of animal whose type is unknown. In generics, an unknown type is represented by the wildcard character "?". To specify a cage capable of holding some kind of animal: Cage<? extends Animal> someCage = ...; Read "? extends Animal" as "an unknown type that is a subtype of Animal, possibly Animal itself", which boils down to "some kind of animal". This is an example of a bounded wildcard, where Animal forms the upper bound of the expected type. If you're asked for a cage that simply holds some kind of animal, you're free to provide a lion cage or a butterfly cage. -------------------------------------------------------------------------------Note: It's also possible to specify a lower bound by using the super keyword instead of extends. The code <? super Animal>, therefore, would be read as "an unknown type that is a supertype of Animal, possibly Animal itself". You can also specify an unknown type with an unbounded wilcard, which simply looks like <?>. An unbounded wildcard is essentially the same as saying <? extends Object>. -------------------------------------------------------------------------------While Cage<Lion> and Cage<Butterfly> are not subtypes of Cage<Animal>, they are in fact subtypes of Cage<? extends Animal>: someCage = lionCage; // OK someCage = butterflyCage; // OK So now the question becomes, "Can you add butterflies and lions directly to someCage?". As you can probably guess, the answer to this question is "no". someCage.add(king); // compiler-time error someCage.add(monarch); // compiler-time error If someCage is a butterfly cage, it would hold butterflies just fine, but the lions would be able to break free. If it's a lion cage, then all would be well with the lions, but the butterflies would fly away. So if you can't put anything at all into someCage, is it useless? No, because you can still read its contents: void feedAnimals(Cage<? extends Animal> someCage) { for (Animal a : someCage) a.feedMe(); } Therefore, you could house your animals in their individual cages, as shown earlier, and invoke this method first for the lions and then for the butterflies: feedAnimals(lionCage); feedAnimals(butterflyCage); Or, you could choose to combine your animals in the all-animal cage instead: feedAnimals(animalCage); Notas de Java SE 2009 Dr. Manuel Mora T. 79/ 150 13. Colecciones A collection — sometimes called a container — is simply an object that groups multiple elements into a single unit. Collections are used to store, retrieve, manipulate, and communicate aggregate data. Typically, they represent data items that form a natural group, such as a poker hand (a collection of cards), a mail folder (a collection of letters), or a telephone directory (a mapping of names to phone numbers). Beneficios: • Reduces programming effort • Increases program speed and quality • Allows interoperability among unrelated APIs • Reduces effort to learn and to use new APIs • Reduces effort to design new APIs • Fosters software reuse Jerarquía de Clases de Colecciones: Colección Set colección sin duplicados SortedSet Set con orden ascendente List una colección ordenada con duplicados posibles, donde cada elemento puede ser accesado directamente Queue una colección con duplicados posibles donde los elementos solo pueden ser accesados estando en el top. Orden puede existir en base a prioridad Map una colección que mapea una lista de llaves a una lista de datos SortedMap Map con orden ascendente Notas de Java SE 2009 Dr. Manuel Mora T. 80/ 150 13. Colecciones Traversing Collections There are two ways to traverse collections: (1) with the for-each construct and (2) by using Iterators. for-each Construct The for-each construct allows you to concisely traverse a collection or array using a for loop — see The for Statement. The following code uses the for-each construct to print out each element of a collection on a separate line. for (Object o : collection) { // código } Iterators An Iterator is an object that enables you to traverse through a collection and to remove elements from the collection selectively, if desired. You get an Iterator for a collection by calling its iterator method. The following is the Iterator interface. public interface Iterator<E> { boolean hasNext(); E next(); void remove(); //optional } // ejemplo de iterator static void filter(Collection<?> c) { for (Iterator<?> it = c.iterator(); it.hasNext(); ) { } } Notas de Java SE 2009 Dr. Manuel Mora T. 81/ 150 13. Colecciones Collection Interface Bulk Operations Bulk operations perform an operation on an entire Collection. containsAll — returns true if the target Collection contains all of the elements in the specified Collection. addAll — adds all of the elements in the specified Collection to the target Collection. removeAll — removes from the target Collection all of its elements that are also contained in the specified Collection. retainAll — removes from the target Collection all its elements that are not also contained in the specified Collection. That is, it retains only those elements in the target Collection that are also contained in the specified Collection. clear — removes all elements from the Collection. The addAll, removeAll, and retainAll methods all return true if the target Collection was modified in the process of executing the operation. As a simple example of the power of bulk operations, consider the following idiom to remove all instances of a specified element, e, from a Collection, c. c.removeAll(Collections.singleton(e)); More specifically, suppose you want to remove all of the null elements from a Collection. c.removeAll(Collections.singleton(null)); This idiom uses Collections.singleton, which is a static factory method that returns an immutable Set containing only the specified element Collection Interface Array Operations The toArray methods are provided as a bridge between collections and older APIs that expect arrays on input. The array operations allow the contents of a Collection to be translated into an array. The simple form with no arguments creates a new array of Object. The more complex form allows the caller to provide an array or to choose the runtime type of the output array. For example, suppose that c is a Collection. The following snippet dumps the contents of c into a newly allocated array of Object whose length is identical to the number of elements in c. Object[] a = c.toArray(); Suppose that c is known to contain only strings (perhaps because c is of type Collection<String>). The following snippet dumps the contents of c into a newly allocated array of String whose length is identical to the number of elements in c. String[] a = c.toArray(new String[0]); Notas de Java SE 2009 Dr. Manuel Mora T. 82/ 150 13. Colecciones The Set interface. public interface Set<E> extends Collection<E> { // Basic operations int size(); boolean isEmpty(); boolean contains(Object element); boolean add(E element); //optional boolean remove(Object element); //optional Iterator<E> iterator(); // Bulk operations boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); //optional boolean removeAll(Collection<?> c); //optional boolean retainAll(Collection<?> c); //optional void clear(); //optional } // Array Operations Object[] toArray(); <T> T[] toArray(T[] a); The Java platform contains three general-purpose Set implementations: HashSet, TreeSet, and LinkedHashSet. HashSet, which stores its elements in a hash table, is the best-performing implementation; however it makes no guarantees concerning the order of iteration. TreeSet, which stores its elements in a red-black tree, orders its elements based on their values; it is substantially slower than HashSet. LinkedHashSet, which is implemented as a hash table with a linked list running through it, orders its elements based on the order in which they were inserted into the set (insertionorder). LinkedHashSet spares its clients from the unspecified, generally chaotic ordering provided by HashSet at a cost that is only slightly higher. Collection<Type> noDups = new LinkedHashSet<Type>(c); Notas de Java SE 2009 Dr. Manuel Mora T. 83/ 150 13. Colecciones Set Interface Basic Operations The size operation returns the number of elements in the Set (its cardinality). The isEmpty method does exactly what you think it would. The add method adds the specified element to the Set if it's not already present and returns a boolean indicating whether the element was added. Similarly, the remove method removes the specified element from the Set if it's present and returns a boolean indicating whether the element was present. The iterator method returns an Iterator over the Set. The following program takes the words in its argument list and prints out any duplicate words, the number of distinct words, and a list of the words with duplicates eliminated. import java.util.*; public class FindDups { public static void main(String[] args) { Set<String> s = new HashSet<String>(); for (String a : args) if (!s.add(a)) { System.out.println("Duplicate detected: " + a); } System.out.println(s.size() + " distinct words: " + s); } } //Now run the program. java FindDups i came i saw i left //The following output is produced. Duplicate detected: i Duplicate detected: i 4 distinct words: [i, left, saw, came] Set Interface Bulk Operations Bulk operations are particularly well suited to Sets; when applied, they perform standard set-algebraic operations. Suppose s1 and s2 are sets. Here's what bulk operations do: s1.containsAll(s2) — returns true if s2 is a subset of s1. (s2 is a subset of s1 if set s1 contains all of the elements in s2.) s1.addAll(s2) — transforms s1 into the union of s1 and s2. (The union of two sets is the set containing all of the elements contained in either set.) s1.retainAll(s2) — transforms s1 into the intersection of s1 and s2. (The intersection of two sets is the set containing only the elements common to both sets.) s1.removeAll(s2) — transforms s1 into the (asymmetric) set difference of s1 and s2. (For example, the set difference of s1 minus s2 is the set containing all of the elements found in s1 but not in s2.) T o calculate the union, intersection, or set difference of two sets nondestructively (without modifying either set), the caller must copy one set before calling the appropriate bulk operation. The following are the resulting idioms. Set<Type> union = new HashSet<Type>(s1); union.addAll(s2); Set<Type> intersection = new HashSet<Type>(s1); intersection.retainAll(s2); Set<Type> difference = new HashSet<Type>(s1); difference.removeAll(s2); Notas de Java SE 2009 Dr. Manuel Mora T. 84/ 150 13. Colecciones Set Interface Basic Operations Let's revisit the FindDups program. Suppose you want to know which words in the argument list occur only once and which occur more than once, but you do not want any duplicates printed out repeatedly. This effect can be achieved by generating two sets — one containing every word in the argument list and the other containing only the duplicates. The words that occur only once are the set difference of these two sets, which we know how to compute import java.util.*; public class FindDups2 { public static void main(String[] args) { Set<String> uniques = new HashSet<String>(); Set<String> dups = new HashSet<String>(); for (String a : args) if (!uniques.add(a)) dups.add(a); // Destructive set-difference uniques.removeAll(dups); System.out.println("Unique words: " + uniques); System.out.println("Duplicate words: " + dups); } } A less common set-algebraic operation is the symmetric set difference — the set of elements contained in either of two specified sets but not in both. The following code calculates the symmetric set difference of two sets nondestructively. Set<Type> symmetricDiff = new HashSet<Type>(s1); symmetricDiff.addAll(s2); Set<Type> tmp = new HashSet<Type>(s1); tmp.retainAll(s2)); symmetricDiff.removeAll(tmp); Notas de Java SE 2009 Dr. Manuel Mora T. 85/ 150 13. Colecciones The List Interface A List is an ordered Collection (sometimes called a sequence). Lists may contain duplicate elements. In addition to the operations inherited from Collection, the List interface includes operations for the following: Positional access — manipulates elements based on their numerical position in the list Search — searches for a specified object in the list and returns its numerical position Iteration — extends Iterator semantics to take advantage of the list's sequential nature Range-view — performs arbitrary range operations on the list. public interface List<E> extends Collection<E> { // Positional access E get(int index); E set(int index, E element); //optional boolean add(E element); //optional void add(int index, E element); //optional E remove(int index); //optional boolean addAll(int index, Collection<? extends E> c); //optional // Search int indexOf(Object o); int lastIndexOf(Object o); // Iteration ListIterator<E> listIterator(); ListIterator<E> listIterator(int index); } // Range-view List<E> subList(int from, int to); The Java platform contains two general-purpose List implementations (se usan en new ). ArrayList, which is usually the better-performing implementation, and LinkedList which offers better performance under certain circumstances. Also, Vector has been retrofitted to implement List. Notas de Java SE 2009 Dr. Manuel Mora T. 86/ 150 13. Colecciones The List Interface package javaapplication6; import java.util.*; public class Demo6 { public static ArrayList<String> dealHand(List<String> deck, int n) { int deckSize = deck.size(); List<String> handView = deck.subList(deckSize-n, deckSize); ArrayList<String> hand = new ArrayList<String>(handView); handView.clear(); return hand; } public static void main(String[] args) { int numHands = Integer.parseInt(args[0]); int cardsPerHand = Integer.parseInt(args[1]); // Make a normal 52-card deck. String[] suit = new String[] {"spades", "hearts", "diamonds", "clubs"}; String[] rank = new String[] {"ace","2","3","4","5","6","7","8", "9","10","jack","queen","king"}; List<String> deck = new ArrayList<String>(); for (int i = 0; i < suit.length; i++) for (int j = 0; j < rank.length; j++) deck.add(rank[j] + " of " + suit[i]); Collections.shuffle(deck); for (int i=0; i < numHands; i++) System.out.println(dealHand(deck, cardsPerHand)); } } Notas de Java SE 2009 Dr. Manuel Mora T. 87/ 150 13. Colecciones List Algorithms Most polymorphic algorithms in the Collections class apply specifically to List. •sort — sorts a List using a merge sort algorithm, which provides a fast, stable sort. (A stable sort is one that does not reorder equal elements.) •shuffle — randomly permutes the elements in a List. •reverse — reverses the order of the elements in a List. •rotate — rotates all the elements in a List by a specified distance. •swap — swaps the elements at specified positions in a List. •replaceAll — replaces all occurrences of one specified value with another. •fill — overwrites every element in a List with the specified value. •copy — copies the source List into the destination List. •binarySearch — searches for an element in an ordered List using the binary search algorithm. •indexOfSubList — returns the index of the first sublist of one List that is equal to another. •lastIndexOfSubList — returns the index of the last sublist of one List that is equal to another import java.util.*; public class Sort { public static void main(String[] args) { List<String> list = Arrays.asList(args); Collections.sort(list); System.out.println(list); } } Notas de Java SE 2009 Dr. Manuel Mora T. 88/ 150 13. Colecciones List Algorithms package javaapplication7; import java.util.*; import java.io.*; public class Demo7 { private static String alphabetize(String s) { char[] a = s.toCharArray(); Arrays.sort(a); return new String(a); } public static void main(String[] args) { int minGroupSize = Integer.parseInt(args[1]); // Read words from file and put into simulated multimap Map<String, List<String>> m = new HashMap<String, List<String>>(); try { Scanner s = new Scanner(new File(args[0])); while (s.hasNext()) { String word = s.next(); String alpha = alphabetize(word); List<String> l = m.get(alpha); if (l == null) m.put(alpha, l=new ArrayList<String>()); l.add(word); } } catch (IOException e) { System.err.println(e); System.exit(1); } // Make a List of all permutation groups above size threshold List<List<String>> winners = new ArrayList<List<String>>(); for (List<String> l : m.values()) if (l.size() >= minGroupSize) winners.add(l); // Sort permutation groups according to size Collections.sort(winners, new Comparator<List<String>>() { public int compare(List<String> o1, List<String> o2) { return o2.size() - o1.size(); }}); // Print permutation groups for (List<String> l : winners ) { System.out.println(l.size() + ": " + l); } } } Notas de Java SE 2009 Dr. Manuel Mora T. 89/ 150 13. Colecciones The Queue Interface A Queue is a collection for holding elements prior to processing. Besides basic Collection operations, queues provide additional insertion, removal, and inspection operations. The Queue interface follows. public interface Queue<E> extends Collection<E> { E element(); boolean offer(E e); E peek(); E poll(); E remove(); } Each Queue method exists in two forms: (1) one throws an exception if the operation fails, and (2) the other returns a special value if the operation fails (either null or false, depending on the operation). The regular structure of the interface is illustrated in the following table. Throws exception Returns special value Insert add(e) offer(e) Remove remove() poll() Examine element() peek() It is possible for a Queue implementation to restrict the number of elements that it holds; such queues are known as bounded. Some Queue implementations in java.util.concurrent are bounded, but the implementations in java.util are not. The add method, which Queue inherits from Collection, inserts an element unless it would violate the queue's capacity restrictions, in which case it throws IllegalStateException. The offer method, which is intended solely for use on bounded queues, differs from add only in that it indicates failure to insert an element by returning false. The remove and poll methods both remove and return the head of the queue. Exactly which element gets removed is a function of the queue's ordering policy. The remove and poll methods differ in their behavior only when the queue is empty. Under these circumstances, remove throws NoSuchElementException, while poll returns null. The element and peek methods return, but do not remove, the head of the queue. They differ from one another in precisely the same fashion as remove and poll: If the queue is empty, element throws NoSuchElementException, while peek returns null Notas de Java SE 2009 Dr. Manuel Mora T. 90/ 150 13. Colecciones The Queue Interface // ejemplo 1 import java.util.*; public class Countdown { public static void main(String[] args) throws InterruptedException { int time = Integer.parseInt(args[0]); Queue<Integer> queue = new LinkedList<Integer>(); // LinkedList es usado para normal Queue for (int i = time; i >= 0; i--) queue.add(i); while (!queue.isEmpty()) { System.out.println(queue.remove()); Thread.sleep(1000); } } } // ejemplo 2 In the following example, a priority queue is used to sort a collection of elements. Again this program is artificial in that there is no reason to use it in favor of the sort method provided in Collections, but it illustrates the behavior of priority queues. static <E> List<E> heapSort(Collection<E> c) { Queue<E> queue = new PriorityQueue<E>(c); List<E> result = new ArrayList<E>(); while (!queue.isEmpty()) result.add(queue.remove()); return result; } Notas de Java SE 2009 Dr. Manuel Mora T. 91/ 150 13. Colecciones Concurrent Queue Implementations The java.util.concurrent package contains a set of synchronized Queue interfaces and classes. • LinkedList implements a normal unbounded and not prioritized queue (FIFO) •BlockingQueue extends Queue with operations that wait for the queue to become nonempty when retrieving an element and for space to become available in the queue when storing an element. This interface is implemented by the following classes: •LinkedBlockingQueue — an optionally bounded FIFO blocking queue backed by linked nodes •ArrayBlockingQueue — a bounded FIFO blocking queue backed by an array •PriorityBlockingQueue — an unbounded blocking priority queue backed by a heap •DelayQueue — a time-based scheduling queue backed by a heap •SynchronousQueue — BlockingQueue interface Notas de Java SE 2009 a simple rendezvous mechanism Dr. Manuel Mora T. that uses 92/ 150 the 13. Colecciones The Map Interface A Map is an object that maps keys to values. A map cannot contain duplicate keys: Each key can map to at most one value. It models the mathematical function abstraction. The Map interface follows. public interface Map<K,V> { // Basic operations V put(K key, V value); V get(Object key); V remove(Object key); boolean containsKey(Object key); boolean containsValue(Object value); int size(); boolean isEmpty(); // Bulk operations void putAll(Map<? extends K, ? extends V> m); void clear(); // Collection Views public Set<K> keySet(); public Collection<V> values(); public Set<Map.Entry<K,V>> entrySet(); } // Interface for entrySet elements public interface Entry { K getKey(); V getValue(); V setValue(V value); } The Java platform contains three general-purpose Map implementations: HashMap, TreeMap, and LinkedHashMap. Their behavior and performance are precisely analogous to HashSet, TreeSet, and LinkedHashSet, as described in The Set Interface section. Also, Hashtable was retrofitted to implement Map. Notas de Java SE 2009 Dr. Manuel Mora T. 93/ 150 13. Colecciones The Map Interface The basic operations of Map (put, get, containsKey, containsValue, size, and isEmpty) behave exactly like their counterparts in Hashtable. The following program generates a frequency table of the words found in its argument list. The frequency table maps each word to the number of times it occurs in the argument list. package javaapplication8; import java.util.*; public class Demo8 { public static void main(String[] args) { Map<String, Integer> m1 = new HashMap<String, Integer>(); Map<String, Integer> m2 = new TreeMap<String, Integer>(); Map<String, Integer> m3 = new LinkedHashMap<String, Integer>(); Integer freq[] = new Integer[3]; // Initialize frequency table from command line for (String a : args) { freq[0]=m1.get(a); freq[1]=m2.get(a); freq[2]=m3.get(a); m1.put(a, (freq[0] == null) ? 1 : freq[0] + 1); m2.put(a, (freq[1] == null) ? 1 : freq[1] + 1); m3.put(a, (freq[2] == null) ? 1 : freq[2] + 1); } System.out.println("HashMap : " + m1.size() + " distinct words:"); System.out.println(m1); System.out.println(); System.out.println("TreeMap : " + m2.size() + " distinct words:"); System.out.println(m2); System.out.println(); System.out.println("LinkedHashMap: " + m3.size() + " distinct words:"); System.out.println(m3); System.out.println(); } } Notas de Java SE 2009 Dr. Manuel Mora T. 94/ 150 13. Colecciones Writing Your Own Comparable Types The Comparable interface consists of the following method: public interface Comparable<T> { public int compareTo(T o); } The compareTo method compares the receiving object with the specified object and returns a negative integer, 0, or a positive integer depending on whether the receiving object is less than, equal to, or greater than the specified object. If the specified object cannot be compared to the receiving object, the method throws a ClassCastException. package javaapplication9; import java.util.*; public class Demo9 { public static void main(String[] args) { Name nameArray[] = { new Name("John", "Lennon"), new Name("Karl", "Marx"), new Name("Groucho", "Marx"), new Name("Oscar", "Grouch") }; List<Name> names = Arrays.asList(nameArray); Collections.sort(names); // name es una clase System.out.println(names); } } package javaapplication9; public class Name implements Comparable<Name> { private final String firstName, lastName; public Name(String firstName, String lastName) { if (firstName == null || lastName == null) throw new NullPointerException(); this.firstName = firstName; this.lastName = lastName; } public String firstName() { return firstName; } public String lastName() { return lastName; } public boolean equals(Object o) { if (!(o instanceof Name)) return false; Name n = (Name)o; return n.firstName.equals(firstName) && n.lastName.equals(lastName); } public int hashCode() { return 31*firstName.hashCode() + lastName.hashCode(); public String toString() { return firstName + " " + lastName; } public int compareTo(Name n) { int lastCmp = lastName.compareTo(n.lastName); return (lastCmp != 0 ? lastCmp : firstName.compareTo(n.firstName)); } } } Notas de Java SE 2009 Dr. Manuel Mora T. 95/ 150 13. Colecciones Comparators What if you want to sort some objects in an order other than their natural ordering? Or what if you want to sort some objects that don't implement Comparable? To do either of these things, you'll need to provide a Comparator — an object that encapsulates an ordering. Like the Comparable interface, the Comparator interface consists of a single method. public interface Comparator<T> { int compare(T o1, T o2); } The compare method compares its two arguments, returning a negative integer, 0, or a positive integer depending on whether the first argument is less than, equal to, or greater than the second. If either of the arguments has an inappropriate type for the Comparator, the compare method throws a ClassCastException. Much of what was said about Comparable applies to Comparator as well. Writing a compare method is nearly identical to writing a compareTo method, except that the former gets both objects passed in as arguments. The compare method has to obey the same four technical restrictions as Comparable's compareTo method for the same reason — a Comparator must induce a total order on the objects it compares. Suppose you have a class called Employee, as follows. public class Employee implements Comparable<Employee> { public Name name() { ... } public int number() { ... } public Date hireDate() { ... } ... } Let's assume that the natural ordering of Employee instances is Name ordering (as defined in the previous example) on employee name. Unfortunately, the boss has asked for a list of employees in order of seniority. import java.util.*; public class EmpSort { static final Comparator<Employee> SENIORITY_ORDER = new Comparator<Employee>() { public int compare(Employee e1, Employee e2) { return e2.hireDate().compareTo(e1.hireDate()); } }; // Employee database static final Collection<Employee> employees = ... ; } public static void main(String[] args) { List<Employee>e = new ArrayList<Employee>(employees); Collections.sort(e, SENIORITY_ORDER); System.out.println(e); } Notas de Java SE 2009 Dr. Manuel Mora T. 96/ 150 14. Concurrencia Processes A process has a self-contained execution environment. A process generally has a complete, private set of basic run-time resources; in particular, each process has its own memory space. Processes are often seen as synonymous with programs or applications. However, what the user sees as a single application may in fact be a set of cooperating processes. To facilitate communication between processes, most operating systems support Inter Process Communication (IPC) resources, such as pipes and sockets. IPC is used not just for communication between processes on the same system, but processes on different systems. Most implementations of the Java virtual machine run as a single process. A Java application can create additional processes using a ProcessBuilder object. Multiprocess applications are beyond the scope of this lesson. Threads Threads are sometimes called lightweight processes. Both processes and threads provide an execution environment, but creating a new thread requires fewer resources than creating a new process. Threads exist within a process — every process has at least one. Threads share the process's resources, including memory and open files. This makes for efficient, but potentially problematic, communication. Multithreaded execution is an essential feature of the Java platform. Every application has at least one thread — or several, if you count "system" threads that do things like memory management and signal handling. But from the application programmer's point of view, you start with just one thread, called the main thread. This thread has the ability to create additional threads, as we'll demonstrate in the next section Threads Utilization Each thread is associated with an instance of the class Thread. There are two basic strategies for using Thread objects to create a concurrent application: •To directly control thread creation and management, simply instantiate Thread each time the application needs to initiate an asynchronous task. It can be realized also using two modes: • Runnable object • Subclass Thread •To abstract thread management from the rest of your application, pass the application's tasks to an executor Executors In all of the previous examples, there's a close connection between the task being done by a new thread, as defined by its Runnable object, and the thread itself, as defined by a Thread object. This works well for small applications, but in large-scale applications, it makes sense to separate thread management and creation from the rest of the application. Objects that encapsulate these functions are known as executors. Notas de Java SE 2009 Dr. Manuel Mora T. 97/ 150 14. Concurrencia Estados de Hilos <threadObj>.start(); <threadObj>.run(); // iniciado por <internal CPU process scheduler> // cuando termina hilo PREPARED EXECUTING <threadObj>.yield(); <threadObj>.wait(); <threadObj>.sleep(); ENDED <OtherthreadObj>.join(); // cuando termina un hilo // cuyo fin es esperado x // otro hilo // cuando reciba un mensaje <threadObj>.notify(); BLOCKED // cuando termine sleep Notas de Java SE 2009 SLEEPED WAITING Dr. Manuel Mora T. 98/ 150 14. Concurrencia Defining and Starting a Thread An application that creates an instance of Thread must provide the code that will run in that thread. There are two ways to do this: Provide a Runnable object. The Runnable interface defines a single method, run, meant to contain the code executed in the thread. The Runnable object is passed to the Thread constructor, as in the HelloRunnable example: public class HelloRunnable implements Runnable { // run es un método de interface Runnable public void run() { System.out.println("Hello from a thread!"); } public static void main(String args[]) { // new Thread (new Thread(new HelloRunnable())).start(); } } Subclass Thread. The Thread class itself implements Runnable, though its run method does nothing. An application can subclass Thread, providing its own implementation of run, as in the HelloThread example: public class HelloThread extends Thread { // run es un método heredado de Thread public void run() { System.out.println("Hello from a thread!"); } } public static void main(String args[]) { // new Thread (new HelloThread()).start(); } Notice that both examples invoke Thread.start in order to start the new thread. Notas de Java SE 2009 Dr. Manuel Mora T. 99/ 150 14. Concurrencia Uso de Thread.sleep(); // variando los tiempos asignados a t.sleep (para Thread secundario) y Thread.sleep (thread primario) // puede visualizarse la asignación de CPU a los 2 hilos // se necesita usar try { } catch(InterruptedException e) { } package javaapplication10; public class Demo10 implements Runnable { static Thread t = null; static String importantInfo[] = { "Mares eat oats", "Does eat oats", "Little lambs eat ivy", "A kid will eat ivy too" }; public void run() { for (int i = 0; i < importantInfo.length; i++) { System.out.println("En hilo con " + i + " -> " + importantInfo[i]); try { System.out.println("hilo: interrupcion generada " + i); t.sleep(10); throw new InterruptedException(); } catch(InterruptedException e) { System.out.println("En hilo con " + i + " -> interrupcion atrapada"); } } } public static void main(String args[]) throws InterruptedException { // new Thread t = new Thread(new Demo10()); t.start(); for (int k = 0; k < importantInfo.length; k++) { System.out.println("En main con " + k + " -> " + importantInfo[k]); try { System.out.println("main: interrupcion generada "+ k ); Thread.sleep(5000); throw new InterruptedException(); } catch(InterruptedException e) { System.out.println("En main con " + k + " -> interrupcion atrapada"); } } } } Notas de Java SE 2009 Dr. Manuel Mora T. 100/ 150 14. Concurrencia Uso de <varThread>.interrupt(), <varThread>.interrupted(), <varThread>.join() An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate. <varThread>.interrupt() envía una interrupción al thread en <varThread> <varThread>.interrupted() verifica si el thread <varthread> tiene status de haber si interrumpido y borra status a false <varThread>.join() espera a que el thread de <varThread> termine <varThread>.join(<time>) espera <time> a que el thread de <varThread> termine NOTA: el OS asigna <slice times> no controlables directamente por estas instrucciones. Thread.join(time> puede ser algo usable. Analice la salida del ejemplo siguiente variando los valores de sleep para main y secundario threads. Notas de Java SE 2009 Dr. Manuel Mora T. 101/ 150 14. Concurrencia package javaapplication11; public class Demo11 implements Runnable { static Thread t = null; static int counterHilo = 0; static int counterMain = 0; static int interrumpirHilo = 1000; static int maxCounterHilo = 10001; static int interrumpirMain = 1000; static int maxCounterMain = 10001; static int valSleep = 1; public void run() { try { Thread.sleep(500); } catch(InterruptedException e) { System.out.println("En hilo delay inicial"); System.out.println("hilo: inicio normal work "); while ((counterHilo <= maxCounterHilo )) { counterHilo++; // cada iteración de 1000 imprimir work done if ((counterHilo % interrumpirHilo)==0) { System.out.println("En hilo work done con counterHilo = " + counterHilo); } // t.interrupted() clears interrupcion y puede ser nuevamente interrumpido if (t.interrupted()) { System.out.println("En hilo interrupcion capturada con counterHilo = " + counterHilo + " - y counterMain = " + counterMain); } } } public static void main(String args[]) { // new Thread t = new Thread(new Demo11()); t.start(); try { Thread.sleep(250); } catch(InterruptedException e) { System.out.println("En main inicio sleep"); } while ((counterMain <= maxCounterMain )) { counterMain++; // cada iteración de 10 interrumpir if ((counterMain % interrumpirMain)==0) { System.out.println("En main con counterMain = " + counterMain); if (t.isAlive()) { System.out.println("En main con counterMain" + counterMain + " -> antes de t.interrupt()"); t.interrupt(); System.out.println("En main con counterMain " + counterMain + " -> despues de t.interrupt()"); } else { System.out.println("En main con counterMain" + counterMain + " -> t is !isAlive"); } //try {System.console().readLine(s);} catch (Exception ioe) { }; } } // t.join(); espera a que termine hilo. Pruebe quitarlo y termina primero main try { t.join(); } catch(InterruptedException e) { }; System.out.println("*** termine en main con counterMain--> " + counterMain); } } Notas de Java SE 2009 Dr. Manuel Mora T. 102/ 150 } 14. Concurrencia package javaapplication12; public class Demo12 { //Display a message, preceded by the name of the current thread static void threadMessage(String message) { String threadName = Thread.currentThread().getName(); System.out.format("%s: %s%n", threadName, message); } private static class MessageLoop implements Runnable { public void run() { String importantInfo[] = { "Mares eat oats", "Does eat oats", "Little lambs eat ivy", "A kid will eat ivy too“ try { for (int i = 0; i < importantInfo.length; i++) { //Pause for 4 seconds Thread.sleep(4000); //Print a message threadMessage(importantInfo[i]); } } catch (InterruptedException e) { threadMessage("I wasn't done!"); } } } }; public static void main(String args[]) throws InterruptedException { //Delay, in milliseconds before we interrupt MessageLoop //thread (default one hour). long patience = 1 * 60 * 60; //If command line argument present, gives patience in seconds. if (args.length > 0) { try { patience = Long.parseLong(args[0]) * 1000; } catch (NumberFormatException e) { System.err.println("Argument must be an integer."); System.exit(1); } } threadMessage("Starting MessageLoop thread"); long startTime = System.currentTimeMillis(); Thread t = new Thread(new MessageLoop()); t.start(); threadMessage("Waiting for MessageLoop thread to finish"); //loop until MessageLoop thread exits while (t.isAlive()) { threadMessage("Still waiting..."); //Wait maximum of 1 second for MessageLoop thread to //finish. t.join(500); if (((System.currentTimeMillis() - startTime) > patience) && threadMessage("Tired of waiting!"); t.interrupt(); //Shouldn't be long now -- wait indefinitely t.join(); } } threadMessage("Finally!"); t.isAlive()) { } } Notas de Java SE 2009 Dr. Manuel Mora T. 103/ 150 14. Concurrencia Synchronized Methods The Java programming language provides two basic synchronization idioms: synchronized methods and synchronized statements. To make a method synchronized, simply add the synchronized keyword to its declaration: public class SynchronizedCounter { private int c = 0; public synchronized void increment() { c++; } public synchronized void decrement() { c--; } public synchronized int value() { return c; } } If count is an instance of SynchronizedCounter, then making these methods synchronized has two effects: •First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object. •Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads. Note that constructors cannot be synchronized — using the synchronized keyword with a constructor is a syntax error. Synchronizing constructors doesn't make sense, because only the thread that creates an object should have access to it while it is being constructed. Notas de Java SE 2009 Dr. Manuel Mora T. 104/ 150 14. Concurrencia Synchronized Statements Another way to create synchronized code is with synchronized statements. Unlike synchronized methods, synchronized statements must specify the object that provides the intrinsic lock: public void addName(String name) { synchronized(this) { lastName = name; nameCount++; } nameList.add(name); } In this example, the addName method needs to synchronize changes to lastName and nameCount, but also needs to avoid synchronizing invocations of other objects' methods. (Invoking other objects' methods from synchronized code can create problems that are described in the section on Liveness.) Synchronized statements are also useful for improving concurrency with fine-grained synchronization. Suppose, for example, class MsLunch has two instance fields, c1 and c2, that are never used together. All updates of these fields must be synchronized, but there's no reason to prevent an update of c1 from being interleaved with an update of c2 — and doing so reduces concurrency by creating unnecessary blocking. Instead of using synchronized methods or otherwise using the lock associated with this, we create two objects solely to provide locks. public class MsLunch { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object(); public void inc1() { synchronized(lock1) { c1++; } } public void inc2() { synchronized(lock2) { c2++; } } } Use this idiom with extreme care. You must be absolutely sure that it really is safe to interleave access of the affected fields. Notas de Java SE 2009 Dr. Manuel Mora T. 105/ 150 14. Concurrencia Guarded Blocks: wait() – notifyAll() Threads often have to coordinate their actions. The most common coordination idiom is the guarded block. Such a block begins by polling a condition that must be true before the block can proceed. There are a number of steps to follow in order to do this correctly. Suppose, for example guardedJoy is a method that must not proceed until a shared variable joy has been set by another thread. Such a method could, in theory, simply loop until the condition is satisfied, But that loop is wasteful, since it executes continuously while waiting. public void guardedJoy() { //Simple loop guard. Wastes processor time. Don't do this! while(!joy) {} System.out.println("Joy has been achieved!"); } A more efficient guard invokes Object.wait to suspend the current thread. The invocation of wait does not return until another thread has issued a notification that some special event may have occurred — though not necessarily the event this thread is waiting for: public synchronized guardedJoy() { //This guard only loops once for each special event, which may not //be the event we're waiting for. while(!joy) { try { wait(); } catch (InterruptedException e) {} } System.out.println("Joy and efficiency have been achieved!"); } When wait is invoked, the thread releases the lock and suspends execution. At some future time, another thread will acquire the same lock and invoke Object.notifyAll, informing all threads waiting on that lock that something important has happened: public synchronized notifyJoy() { joy = true; notifyAll(); } Some time after the second thread has released the lock, the first thread reacquires the lock and resumes by returning from the invocation of wait. Notas de Java SE 2009 Dr. Manuel Mora T. 106/ 150 14. Concurrencia Guarded Blocks: wait() – notifyAll() In this example, the data is a series of text messages, which are shared through an object of type Drop: public class Drop { //Message sent from producer to consumer. private String message; //True if consumer should wait for producer to send message, false //if producer should wait for consumer to retrieve message. private boolean empty = true; public synchronized String take() { //Wait until message is available. while (empty) { try { wait(); } catch (InterruptedException e) {} } //Toggle status. empty = true; //Notify producer that status has changed. notifyAll(); return message; } public synchronized void put(String message) { //Wait until message has been retrieved. while (!empty) { try { wait(); } catch (InterruptedException e) {} } //Toggle status. empty = false; //Store message. this.message = message; //Notify consumer that status has changed. notifyAll(); } } Notas de Java SE 2009 Dr. Manuel Mora T. 107/ 150 14. Concurrencia Guarded Blocks: wait() – notifyAll() The producer thread, defined in Producer, sends a series of familiar messages. The string "DONE" indicates that all messages have been sent. To simulate the unpredictable nature of real-world applications, the producer thread pauses for random intervals between messages. import java.util.Random; public class Producer implements Runnable { private Drop drop; public Producer(Drop drop) { this.drop = drop; } public void run() { String importantInfo[] = { "Mares eat oats", "Does eat oats", "Little lambs eat ivy", "A kid will eat ivy too" }; Random random = new Random(); for (int i = 0; i < importantInfo.length; i++) { drop.put(importantInfo[i]); try { Thread.sleep(random.nextInt(5000)); } catch (InterruptedException e) {} } drop.put("DONE"); } } The consumer thread, defined in Consumer, simply retrieves the messages and prints them out, until it retrieves the "DONE" string. This thread also pauses for random intervals. import java.util.Random; public class Consumer implements Runnable { private Drop drop; public Consumer(Drop drop) { this.drop = drop; } public void run() { Random random = new Random(); for (String message = drop.take(); ! message.equals("DONE"); message = drop.take()) { System.out.format("MESSAGE RECEIVED: %s%n", message); try { Thread.sleep(random.nextInt(5000)); } catch (InterruptedException e) {} } } } Finally, here is the main thread, defined in ProducerConsumerExample, that launches the producer and consumer threads. public class ProducerConsumerExample { public static void main(String[] args) { Drop drop = new Drop(); (new Thread(new Producer(drop))).start(); (new Thread(new Consumer(drop))).start(); } } Notas de Java SE 2009 Dr. Manuel Mora T. 108/ 150 14. Concurrencia Strategy for Defining Immutable Objects The class, SynchronizedRGB, defines objects that represent colors. Each object represents the color as three integers that stand for primary color values and a string that gives the name of the color. public class SynchronizedRGB { //Values must be between 0 and 255. private int red; private int green; private int blue; private String name; private void check(int red, int green, int blue) { if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) { throw new IllegalArgumentException(); } } public SynchronizedRGB(int red, int green, int blue, String name) { check(red, green, blue); this.red = red; this.green = green; this.blue = blue; this.name = name; } public void set(int red, int green, int blue, String name) { check(red, green, blue); synchronized (this) { this.red = red; this.green = green; this.blue = blue; this.name = name; } } public synchronized int getRGB() { return ((red << 16) | (green << 8) | blue); } public synchronized String getName() { return name; } public synchronized void invert() { red = 255 - red; green = 255 - green; blue = 255 - blue; name = "Inverse of " + name; } } SynchronizedRGB must be used carefully to avoid being seen in an inconsistent state. Suppose, for example, a thread executes the following code: SynchronizedRGB color = new SynchronizedRGB(0, 0, 0, "Pitch Black"); ... int myColorInt = color.getRGB(); //Statement 1 String myColorName = color.getName(); //Statement 2 If another thread invokes color.set after Statement 1 but before Statement 2, the value of myColorInt won't match the value of myColorName. To avoid this outcome, the two statements must be bound together: synchronized (color) { int myColorInt = color.getRGB(); String myColorName = color.getName(); } This kind of inconsistency is only possible for mutable objects — it will not be an issue for the immutable version of Synchronized Notas de Java SE 2009 Dr. Manuel Mora T. 109/ 150 14. Concurrencia Strategy for Defining Immutable Objects The following rules define a simple strategy for creating immutable objects. • Don't provide "setter" methods — methods that modify fields or objects referred to by fields. • Make all fields final and private. • Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods. • If the instance fields include references to mutable objects, don't allow those objects to be changed: • Don't provide methods that modify the mutable objects. • Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods. Applying this strategy to SynchronizedRGB results in the following steps: final public class ImmutableRGB { //Values must be between 0 and 255. final private int red; final private int green; final private int blue; final private String name; private void check(int red, int green, int blue) { if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) { throw new IllegalArgumentException(); } } public ImmutableRGB(int red, int green, int blue, String name) { check(red, green, blue); this.red = red; this.green = green; this.blue = blue; this.name = name; } public int getRGB() { return ((red << 16) | (green << 8) | blue); } public String getName() { return name; } public ImmutableRGB invert() { return new ImmutableRGB(255 - red, 255 - green, 255 - blue, "Inverse of " + name); } } Notas de Java SE 2009 Dr. Manuel Mora T. 110/ 150 15. Applets Applets: Introducción An applet is a special kind of Java program that a browser enabled with Java technology can download from the internet and run. An applet is typically embedded inside a web-page and runs in the context of the browser: <html> <applet code=AppletWorld.class width="200" height="200"> </applet> </html> • An applet must be a subclass of the java.applet.Applet class, which provides the standard interface between the applet and the browser environment. import java.applet.Applet; public class NewApplet extends Applet { /** Initializes the applet NewApplet */ public void init() { } } • Swing provides a special subclass of Applet, called javax.swing.JApplet, which should be used for all applets that use Swing components to construct their GUIs import javax.swing.JApplet; import java.awt.Graphics; public class HelloWorld extends JApplet { // paint es un método sobre-escrito de la clase Graphics public void paint(Graphics g) { g.drawRect(0, 0, getSize().width - 1, getSize().height - 1); g.drawString("Hello world!", 5, 15); } } Notas de Java SE 2009 Dr. Manuel Mora T. 111/ 150 15. Applets Applets: LifeCycle • The applet class is declared public so appletviewer/any browser can access it. • The applet class descends from Applet/JApplet and an application class descends from Frame/JFrame. • The applet version has no main method. • The application constructor is replaced in the applet by start and init methods. • GUI components are added directly to the Applet; whereas, in the case of an application, GUI components are added to the content pane of its JFrame object. • Methods indispensables: init(), start(), stop(), destroy() (que usualmente son overriden) // applet es cargado por 1ª. vez en el browser // cuando el usuario deja la webpage <applet>.init(); Applet Inicializado Applet Comenzado <applet>.start(); Applet Detenido <applet>.stop(); // applet.start es llamado por init() automáticamente <applet>.destroy(); // cuando el usuario retorna al webpage Applet Destruido Current browsers impose the following restrictions on any applet that is loaded over the network: •An applet cannot load libraries or define native methods. •It cannot ordinarily read or write files on the host that's executing it. •It cannot make network connections except to the host that it came from. •It cannot start any program on the host that's executing it. •It cannot read certain system properties. •Windows that an applet brings up look different than windows that an application brings up. Notas de Java SE 2009 Dr. Manuel Mora T. 112/ 150 15. Applets Applets: LifeCycle • Methods indispensables: init(), start(), stop(), destroy() (que usualmente son overriden) import java.applet.Applet; import java.awt.Graphics; import java.io.IOException; public class NewApplet1 extends Applet { StringBuffer buffer; int y = 15; public void init() { buffer = new StringBuffer("vacio..." + "["+ y + "]"); y=y+10; addItem("initializing applet... "+ "["+ y + "]"); } public void start() { y=y+10; addItem("starting applet... " + "["+ y + "]"); y=y+10; doAppletProcess(); } public void stop() { addItem("stopping... " + "["+ y + "]"); try {System.in.read();} catch(IOException e){ }; } public void destroy() { addItem("preparing for unloading..." + "["+ y + "]"); } private void doAppletProcess(){ addItem("doAppletProcess... " + "["+ y + "]"); } private void addItem(String newWord) { buffer.append(newWord); repaint(); } public void paint(Graphics g) { g.drawRect(0, 0, getWidth() - 1, getHeight() - 1); g.drawString("y en GWS["+ y + "]"+ buffer.toString(), 5, y); g.drawString("y en GWS["+ y + "]"+ buffer.toString(), 5, y+10); } } • NOTE LA SALIDA: paint se ejecuta al final de init start (doAppletProcess). No se puede visualizar mensajes de stop y destroy Notas de Java SE 2009 Dr. Manuel Mora T. 113/ 150 15. Applets Applets: Eventos • Applets inherit a group of event-handling methods from the Container class. The Container class defines several methods, such as processKeyEvent and processMouseEvent, for handling particular types of events, and then one catch-all method called processEvent. To react to an event, an applet must override the appropriate event-specific method. For example, the following program, SimpleClick, implements a MouseListener and overrides the mouseClicked method. import java.applet.Applet; import java.awt.Graphics; import java.awt.event.MouseListener; import java.awt.event.MouseEvent; public class NewApplet2 extends Applet implements MouseListener { StringBuffer buffer = new StringBuffer("Applet2 ..."); int y = 10; int xx, yy; public void init() { addMouseListener(this); } public void start() { doAppletProcess(); } public void stop() { } public void destroy() { } private void doAppletProcess(){ addItem("doAppletProcess... " + "["+ y + "]"); } private void addItem(String newWord) { buffer=buffer.delete(0,buffer.length()-1); buffer.append(newWord); repaint(); } public void paint(Graphics g) { g.draw3DRect(0, 0, getWidth()-1, getHeight()-1, true); g.drawString(buffer.toString(), xx, yy); } public void mouseEntered(MouseEvent event) { xx=event.getX(); yy=event.getY(); addItem("mouseEntered... " + "["+ xx + "," + yy + "] ..."); } public void mouseExited(MouseEvent event) { } public void mousePressed(MouseEvent event) { } public void mouseReleased(MouseEvent event) { } public void mouseClicked(MouseEvent event) { xx=event.getX(); yy=event.getY(); addItem("mouseClick!... " + "["+ xx + "," + yy + "] ..."); } } Notas de Java SE 2009 Dr. Manuel Mora T. 114/ 150 15. Applets Applets: Documentos • Have you ever wanted an applet to display formatted HTML text? There's an easy way to do it: Ask the browser to display the text for you. With the AppletContext showDocument methods, an applet can tell the browser which URL to show and in which browser window. Here are the two forms of showDocument: •public void showDocument(java.net.URL url) •public void showDocument(java.net.URL url, String targetWindow) • The one-argument form of showDocument simply tells the browser to display the document at the specified URL, without specifying the window to display the document in. Terminology Note: In this discussion, frame refers not to a Swing JFrame, but to an HTML frame within a browser window. The two-argument form of showDocument lets you specify which window or HTML frame to display the document in. The second argument can have the values listed below. •"_blank" Display the document in a new, nameless window. •"windowName" Display the document in a window named windowName. This window is created if necessary. •"_self" Display the document in the window and frame that contain the applet. •"_parent" Display the document in parent frame of the applet's frame. If the applet frame has no parent frame, this acts the same as "_self". •"_top" Display the document in the top-level frame. If the applet's frame is the top-level frame, this acts the same as "_self". • The following applet lets you try every option of both forms of showDocument. The applet brings up a window that lets you type in a URL and choose any of the showDocument options. When you press Return or click the Show document button, the applet calls showDocument. Notas de Java SE 2009 Dr. Manuel Mora T. 115/ 150 15. Applets Applets: Documentos • NOTE que el Applet incluye 1 u otras clases adicionales que utiliza. Dichas clases deben ser también compiladas y accesibles al directorio del Applet. import java.applet.AppletContext; import javax.swing.*; import java.awt.GridBagLayout; import java.awt.GridBagConstraints; import java.awt.Insets; import java.awt.event.*; import java.net.URL; import java.net.MalformedURLException; public class NewJApplet1 extends JApplet implements ActionListener { URLWindow urlWindow; public void init() { try { SwingUtilities.invokeAndWait( new Runnable() { public void run() { createGUI(); } }); } catch (Exception e) { System.err.println("createGUI didn't successfully complete"); } } private void createGUI() { JButton button = new JButton("Bring up URL window"); button.addActionListener(this); add(button); JFrame.setDefaultLookAndFeelDecorated(true); urlWindow = new URLWindow(getAppletContext()); urlWindow.pack(); } public void destroy() { try { SwingUtilities.invokeAndWait( new Runnable() { public void run() { destroyGUI(); } }); } catch (Exception e) { } } private void destroyGUI() { urlWindow.setVisible(false); urlWindow = null; } public void actionPerformed(ActionEvent event) { // se hace visible la ventana de datos urlWindow.setVisible(true); } } Notas de Java SE 2009 Dr. Manuel Mora T. 116/ 150 15. Applets Applets: Documentos • NOTA: la clase URLWindow es parte del archivo de Applet NewApplet1. class URLWindow extends JFrame implements ActionListener { JTextField urlField; JComboBox choice; AppletContext appletContext; public URLWindow(AppletContext appletContext) { super("Show a Document!"); this.appletContext = appletContext; JPanel contentPane = new JPanel(new GridBagLayout()); setContentPane(contentPane); contentPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; JLabel label1 = new JLabel("URL of document to show: ", JLabel.TRAILING); add(label1, c); urlField = new JTextField("http://java.sun.com/", 20); label1.setLabelFor(urlField); urlField.addActionListener(this); c.gridwidth = GridBagConstraints.REMAINDER; c.weightx = 1.0; add(urlField, c); JLabel label2 = new JLabel("Window/frame to show it in: ", JLabel.TRAILING); c.gridwidth = 1; c.weightx = 0.0; add(label2, c); String[] strings = { "(browser's choice)", //don't specify "My Personal Window", //a window named "My Personal Window" "_blank", //a new, unnamed window "_self", "_parent", "_top" //the Frame that contained this applet }; choice = new JComboBox(strings); label2.setLabelFor(choice); c.fill = GridBagConstraints.NONE; c.gridwidth = GridBagConstraints.REMAINDER; c.insets = new Insets(5,0,0,0); c.anchor = GridBagConstraints.LINE_START; add(choice, c); JButton button = new JButton("Show document"); button.addActionListener(this); c.weighty = 1.0; c.ipadx = 10; c.ipady = 10; c.insets = new Insets(10,0,0,0); c.anchor = GridBagConstraints.PAGE_END; add(button, c); } public void actionPerformed(ActionEvent event) { String urlString = urlField.getText(); URL url = null; try { url = new URL(urlString); } catch (MalformedURLException e) { System.err.println("Malformed URL: " + urlString); } if (url != null) { if (choice.getSelectedIndex() == 0) { appletContext.showDocument(url); } else { appletContext.showDocument(url, (String)choice.getSelectedItem()); } } } } Notas de Java SE 2009 Dr. Manuel Mora T. 117/ 150 15. Applets Applets: Parámetros • Parameters are to applets what command-line arguments are to applications. They allow the user to customize the applet's operation. By defining parameters, you can increase your applet's flexibility, making your applet work in multiple situations without recoding and recompiling it. • Parameter values are all strings. Whether or not the user puts quotation marks around a parameter value, that value is passed to your applet as a string. However, your applet can interpret the string in many ways. Applets typically interpret a parameter value as one of the following types: • • • • • • A URL An integer A floating-point number A boolean value -- typically "true"/"false" or "yes"/"no" A string -- for example, the string to use as a window title A list of any of the above Ejemplo: <APPLET CODE=SampleApplet.class CODEBASE=example WIDTH=350 HEIGHT=60> <PARAM NAME=windowClass VALUE=BorderWindow> <PARAM NAME=windowTitle VALUE="BorderLayout"> <PARAM NAME=buttonText VALUE="Click here to see a BorderLayout in action"> </APPLET> Notas de Java SE 2009 Dr. Manuel Mora T. 118/ 150 15. Applets Applets: GUI • Un esquema general para definir Applets en formato GUI, de manera directa es similar al presentado en siguiente seccion GUI. La otra opción es usar un entorno de desarrollo como netbeans. • El esquema general (basado en siguiente sección es el siguiente): 1. Defina una clase que extienda JApplet e implemente ActionListener, ComponentListener. Esto último para tener acceso a eventos (de mouse, teclado). Defina también las bibliotecas usuales. Defina también aquí las variables principales de manera global a la clase. import javax.swing.*; import java.awt.event.*; import java.awt.event.ComponentListener; public class JAppletDemo1 extends JApplet implements ActionListener, ComponentListener { JLabel label[] = {new JLabel("Hello World 1"), new JLabel("Hello 2"), new JLabel("Hello 3")}; JButton buttons[]= { new JButton("B1"), new JButton("B2"), new JButton("B3")}; JTextField datos[]= { new JTextField("texto 1"), new JTextField("texto 2"), new JTextField("texto 3")}; JToggleButton jtb = new JToggleButton("ok"); 2. Defina en el método constructor de la clase a través de un objeto JPanel, todos los controles GUI necesarios. public JAppletDemo1() { setSize(795, 395); setLayout(null); // setLayout(null) permite usar posiciones absolutas (x,y) en pantalla // defina los controles GUI, añada a clase JAppletDemo1 setVisible(true); } 3. Defina un procedimiento para crear un objeto JFrame, donde se instanciará su <Pane> con el JPanel. public static void createAndShowGUI() { JFrame f = new JFrame("Hello World Swing in JApplet"); JAppletDemo1 GUIPane = new JAppletDemo1(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setSize(800, 400); f.setContentPane(GUIPane); f.setVisible(true); } 4. Defina los procedimientos para manejar los eventos. 5. Defina el proceso principal <init> y <start>. <init> cual invocará al procedimiento creado en paso #3 y a <start>. Notas de Java SE 2009 Dr. Manuel Mora T. 119/ 150 15. Applets Applets: GUI /* 1. */ Defina una clase que extienda JApplet e implemente ActionListener, ComponentListener. Esto último para tener acceso a eventos (de mouse, teclado). Defina también las bibliotecas usuales. Defina también aquí las variables principales de manera global a la clase. import javax.swing.*; import java.awt.event.*; import java.awt.event.ComponentListener; public class JAppletDemo1 extends JApplet implements ActionListener, ComponentListener { JLabel label[] = {new JLabel("Hello World 1"), new JLabel("Hello 2"), new JLabel("Hello 3")}; JButton buttons[]= { new JButton("B1"), new JButton("B2"), new JButton("B3")}; JTextField datos[]= { new JTextField("texto 1"), new JTextField("texto 2"), new JTextField("texto 3")}; JToggleButton jtb = new JToggleButton("ok"); /* 2. Defina en el método constructor de la clase a través de un objeto JPanel, todos los controles GUI necesarios. */ public JAppletDemo1() { setSize(795, 395); setLayout(null); for (int i=0; i<3; i++) { label[i].setVisible(true); label[i].setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 255, 255), 3, true)); buttons[i].setVisible(true); buttons[i].setBorder(new javax.swing.border.LineBorder(new java.awt.Color(255, 255, 0), 3, true)); datos[i].setVisible(true); datos[i].setBorder(new javax.swing.border.LineBorder(new java.awt.Color(255, 0, 255), 3, true)); datos[i].addActionListener(this); label[i].setBounds(50, 100+i*20, 150, 25); buttons[i].setBounds(250, 100+i*20, 150, 25); datos[i].setBounds(450, 100+i*20, 150, 25); buttons[i].setActionCommand("cmd-"+i); buttons[i].addActionListener(this); add(label[i]); add(buttons[i]); add(datos[i]); } jtb.setBounds(50, 50, 50,20); jtb.setVisible(true); jtb.setActionCommand("toggle-cmd"); jtb.addActionListener(this); //jtb.addActionListener(new java.awt.event.ActionListener() { // public void actionPerformed(java.awt.event.ActionEvent evt) { // jToggleButton1ActionPerformed(evt); // } //}); add(jtb); setVisible(true); } Notas de Java SE 2009 Dr. Manuel Mora T. 120/ 150 15. Applets Applets: GUI /* 3. */ Defina un procedimiento para crear un objeto JFrame, donde se instanciará su <Pane> con el JPanel. public static void createAndShowGUI() { JFrame f = new JFrame("HelloWorldSwing"); JAppletDemo1 GUIPane = new JAppletDemo1(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setSize(800, 400); f.setContentPane(GUIPane); f.setVisible(true); } /* 4. Defina los procedimientos para manejar los eventos. */ private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: datos[0].setText("Action by jButton1"); datos[0].repaint(); } public void componentHidden(ComponentEvent e) { } public void componentMoved(ComponentEvent e) { } public void componentResized(ComponentEvent e) { } public void componentShown(ComponentEvent e) { } public void actionPerformed(ActionEvent e) { String cmd = new String("cmd null"); cmd = e.getActionCommand(); if (cmd.equals("cmd-0")) { datos[0].setText(cmd); } else if (cmd.equals("cmd-1")) { datos[1].setText(cmd); } else if (cmd.equals("cmd-2")) { datos[2].setText(cmd); } else if (cmd.equals("toggle-cmd")) { datos[0].setText(cmd); } else { for (int i=0; i<3; i++) { datos[i].setText("******************"); } for (int i=0; i<3; i++) { datos[i].repaint(); } } /* 5. */ } Defina el proceso principal <init> y <start>. <init> cual invocará al procedimiento creado en paso #3 y a <start>. public void init() { javax.swing.SwingUtilities.invokeLater( new Runnable() {public void run() {createAndShowGUI();} } ); } public void start() { } } Notas de Java SE 2009 Dr. Manuel Mora T. 121/ 150 16. GUI GUI: Generalidades • To create a Java program with a graphical user interface (GUI), the Swing toolkit includes a rich set of components for building GUIs and adding interactivity to Java applications. Swing includes all the components you would expect from a modern toolkit: table controls, list controls, tree controls, buttons, and labels. Swing provides [Java Look l] or [Windows Look]. The group of GUI controls are the following: Basic Controls • JButton • JCheckBox • JComboBox • JList • JMenu • JRadioButton • JSlider • JSpinner • JTextField • JPasswordField Formatted Controls •JColorChooser • JEditorPane • JTextPane • JFileChooser • JTable • JTextArea • JTree Top-level Containers • JApplet • JDialog • JFrame General Purpose Containers • JPanel • JScrollPane • JSplitPane • JTabbedPane • JToolBar Special Purpose Containers • JInternalFrame • JLayeredPanel • JRootPane Non-editable Controls • JLabel • JProgressBar • JSeparator • JToolTip Notas de Java SE 2009 Dr. Manuel Mora T. 122/ 150 16. GUI GUI: Generalidades • A Class Hierarchy of Swing components is the following (general view) JFrame JDialog Japplet JComponent General Purpose Containers • JPanel • JScrollPane • JSplitPane • JTabbedPane • JToolBar Special Purpose Containers • JInternalFrame • JLayeredPanel • JRootPane JFrame 1 1..* Container (general, special) 1 1..* Controls (basic, formatted, non-editable) Notas de Java SE 2009 Basic Controls • JButton • JCheckBox • JComboBox • JList • JMenu • JRadioButton • JSlider • JSpinner • JTextField • JPasswordField Formatted Controls •JColorChooser • JEditorPane • JTextPane • JFileChooser • JTable • JTextArea • JTree Non-editable Controls • JLabel • JProgressBar • JSeparator • JToolTip Dr. Manuel Mora T. 123/ 150 16. GUI GUI: Estructura de una Clase usando Swing GUI • Hay diversas maneras de desarrollar un sistema usando clases de Swing GUI. En particular las 2 maneras principales son: • Definiendo directamente todos los componentes • Usando un ambiente de desarrollo como netbeans • La mejor manera es usar un ambiente de desarrollo GUI como netbeans, ya que el ambiente genera código GUI especializado, que definirlo directamene es realmente un trabajo excesivo (quizás mayor que el invertido en la lógica princiapal de sistema). Sin embargo, de manera general se pueden dar los siguientes lineamientos para definir una clase Swing GUI de manera directa conmo sigue: 1. Defina una clase que extienda JPanel e implemente ActionListener, ComponentListener. Esto último para tener acceso a eventos (de mouse, teclado). Defina también las bibliotecas usuales. Defina también aquí las variables principales de manera global a la clase. import javax.swing.*; import java.awt.event.*; import java.awt.event.ComponentListener; public class Demo1 extends JPanel implements ActionListener, ComponentListener { JLabel label[] = {new JLabel("Hello World 1"), new JLabel("Hello 2"), new JLabel("Hello 3")}; JButton buttons[]= { new JButton("B1"), new JButton("B2"), new JButton("B3")}; JTextField datos[]= { new JTextField("texto 1"), new JTextField("texto 2"), new JTextField("texto 3")}; JToggleButton jtb = new JToggleButton("ok"); 2. Defina en el método constructor de la clase a través de un objeto JPanel, todos los controles GUI necesarios. 3. Defina un procedimiento para crear un objeto JFrame, donde se instanciará su <Pane> con el JPanel. 4. Defina los procedimientos para manejar los eventos. 5. Defina el proceso principal <main> el cual invocará al procedimiento creado en paso #3. Notas de Java SE 2009 Dr. Manuel Mora T. 124/ 150 16. GUI import javax.swing.*; import java.awt.event.*; import java.awt.event.ComponentListener; // 1. Se define una clase que extiende JPanel e implementa ActionListener public class Demo1 extends JPanel implements ActionListener, ComponentListener { JLabel label[] = {new JLabel("Hello World 1"), new JLabel("Hello 2"), new JLabel("Hello 3")}; JButton buttons[]= { new JButton("B1"), new JButton("B2"), new JButton("B3")}; JTextField datos[]= { new JTextField("texto 1"), new JTextField("texto 2"), new JTextField("texto 3")}; JToggleButton jtb = new JToggleButton("ok"); // 2. Se define el constructor de la clase con todos los controles GUI // 2.1 Use this.setLayout(null) en JPanel para que se reconozcan los valores absolutos de coordenadas. // 2.2 Use this.setSize(w,h) para definir tamaños de JPanel // 2.4 Use en los controles setBorder(), setBounds(), setVisible(), // 2.5 Añada en controles de acciones con control.setActionCommand() y control.addActionListener() eventos // NOTA: es posible definir métodos propios para un evento de un control usando: // <controlGUI>.addActionListener(new java.awt.event.ActionListener() { // public void actionPerformed(java.awt.event.ActionEvent evt) { // <metodoParaManejarEvento>(evt); // } // 2.6 Añada los controles al objeto tipo JPanel con this.add() // 2.7 Haga visible el objeto JPanel public Demo1() { setSize(795, 395); setLayout(null); for (int i=0; i<3; i++) { label[i].setVisible(true); label[i].setBorder(new javax.swing.border.LineBorder(new java.awt.Color(0, 255, 255), 3, true)); buttons[i].setVisible(true); buttons[i].setBorder(new javax.swing.border.LineBorder(new java.awt.Color(255, 255, 0), 3, true)); datos[i].setVisible(true); datos[i].setBorder(new javax.swing.border.LineBorder(new java.awt.Color(255, 0, 255), 3, true)); datos[i].addActionListener(this); label[i].setBounds(50, 100+i*20, 150, 25); buttons[i].setBounds(250, 100+i*20, 150, 25); datos[i].setBounds(450, 100+i*20, 150, 25); buttons[i].setActionCommand("cmd-"+i); buttons[i].addActionListener(this); add(label[i]); add(buttons[i]); add(datos[i]); } jtb.setBounds(50, 50, 50,20); jtb.setVisible(true); jtb.setActionCommand("toggle-cmd"); jtb.addActionListener(this); //jtb.addActionListener(new java.awt.event.ActionListener() { // public void actionPerformed(java.awt.event.ActionEvent evt) { // jToggleButton1ActionPerformed(evt); // } //}); add(jtb); setVisible(true); } Notas de Java SE 2009 Dr. Manuel Mora T. 125/ 150 16. GUI // 3. Defina un procedimiento para crear un objeto JFrame, donde se instanciará su <Pane> con el JPanel. public static void createAndShowGUI() { //Create and set up the window. JFrame f = new JFrame("HelloWorldSwing"); Demo1 GUIPane = new Demo1(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.setSize(800, 400); f.setContentPane(GUIPane); f.setVisible(true); } // 4. Defina los procedimientos para manejar los eventos. public void actionPerformed(ActionEvent e) { String cmd = new String("cmd null"); cmd = e.getActionCommand(); if (cmd.equals("cmd-0")) { datos[0].setText(cmd); } else if (cmd.equals("cmd-1")) { datos[1].setText(cmd); } else if (cmd.equals("cmd-2")) { datos[2].setText(cmd); } else if (cmd.equals("toggle-cmd")) { datos[0].setText(cmd); } else { for (int i=0; i<3; i++) { datos[i].setText("******************"); } } for (int i=0; i<3; i++) { datos[i].repaint(); } } // Estos procedimientos son adicionales para eventos de Component. public void componentHidden(ComponentEvent e) { } public void componentMoved(ComponentEvent e) { } public void componentResized(ComponentEvent e) { } public void componentShown(ComponentEvent e) { } // Ejemplo de manejo directo de un evento: <metodoParaManejarEvento>=jToggleButton1ActionPerformed private void jToggleButton1ActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: datos[0].setText("Action by jButton1"); datos[0].repaint(); } // Defina el proceso principal <main> el cual invocará al procedimiento creado en paso #3. public static void main( String[] args ) { javax.swing.SwingUtilities.invokeLater( new Runnable() { public void run() { createAndShowGUI(); } } ); } } Notas de Java SE 2009 Dr. Manuel Mora T. 126/ 150 16. GUI GUI: Generalidades Top-level Containers • JApplet • JDialog • JFrame Notas de Java SE 2009 Dr. Manuel Mora T. 127/ 150 16. GUI GUI: Generalidades General Purpose Containers • JPanel • JScrollPane • JSplitPane • JTabbedPane • JToolBar Notas de Java SE 2009 Dr. Manuel Mora T. 128/ 150 16. GUI GUI: Generalidades Special Purpose Containers • JInternalFrame • JLayeredPanel • JRootPane Notas de Java SE 2009 Dr. Manuel Mora T. 129/ 150 16. GUI GUI: Generalidades Basic Controls • JButton • JCheckBox • JComboBox • JList • JMenu • JRadioButton • JSlider • JSpinner • JTextField • JPasswordField Notas de Java SE 2009 Dr. Manuel Mora T. 130/ 150 16. GUI GUI: Generalidades Formatted Controls •JColorChooser • JEditorPane • JTextPane • JFileChooser • JTable • JTextArea • JTree Notas de Java SE 2009 Dr. Manuel Mora T. 131/ 150 16. GUI GUI: Generalidades Non-editable Controls • JLabel • JProgressBar • JSeparator • JToolTip Notas de Java SE 2009 Dr. Manuel Mora T. 132/ 150 16. GUI GUI: JFrame / Top-level Containers •A Frame is a top-level window with a title and a border. A frame, implemented as an instance of the JFrame class, is a window that has decorations such as a border, a title, and supports button components that close or iconify the window. Applications with a GUI usually include at least one frame. Applets sometimes use frames, as well. Top-level Containers use two main components: ContentPane and MenuBar. In ContentPane are added all GUI controls. • JFrame Constructores: JFrame frame = new JFrame(); JFrame frame = new JFrame("FrameDemo"); • JFrame Usuales Métodos: // especificar acción al cerrar la ventana frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // constantes posibles son: JFrame.DO_NOTHING_ON_CLOSE JFrame.HIDE_ON_CLOSE JFrame.DISPOSE_ON_CLOSE JFrame.EXIT_ON_CLOSE // especificar tamaño, localización, visibilidad y ajuste a tamaño mínimo factible frame.setSize(new Dimension(w,h)); frame.setPreferredSize(new Dimension(w,h)); frame.setResizable(<boolean>); frame.setLocation(x,y); frame.setVisible(<boolean>); frame.pack(); // preferred sizes are used in internal controls // traer o establecer el ContentPane: The content pane contains the visible GUI components // within the frame. frame.setContentPane( <container>); frame.getContentPane().<método> // usualmente add() // traer o establecer el JMenuBar: the frame menu bar to manage a set of menus for the frame. frame.setJMenuBar( <JMenuBar>); frame.getJMenuBar().<método> Notas de Java SE 2009 Dr. Manuel Mora T. 133/ 150 16. GUI GUI: JFrame / Top-level Containers •A Frame is a top-level window with a title and a border. A frame, implemented as an instance of the JFrame class, is a window that has decorations such as a border, a title, and supports button components that close or iconify the window. Applications with a GUI usually include at least one frame. Applets sometimes use frames, as well. Top-level Containers use two main components: ContentPane and MenuBar. In ContentPane are added all GUI controls. • JFrame Usuales Métodos: // especificar acción al cerrar la ventana frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // constantes posibles son: JFrame.DO_NOTHING_ON_CLOSE JFrame.HIDE_ON_CLOSE JFrame.DISPOSE_ON_CLOSE JFrame.EXIT_ON_CLOSE // especificar tamaño, localización, visibilidad y ajuste a tamaño mínimo factible frame.setSize(new Dimension(w,h)); frame.setPreferredSize(new Dimension(w,h)); frame.setResizable(<boolean>); frame.setLocation(x,y); frame.setVisible(<boolean>); frame.pack(); // preferred sizes are used in internal controls // traer o establecer el ContentPane: The content pane contains the visible GUI components // within the frame. frame.setContentPane( <container>); frame.getContentPane().<método> // usualmente add() // traer o establecer el JMenuBar: the frame menu bar to manage a set of menus for the frame. frame.setJMenuBar( <JMenuBar>); frame.getJMenuBar().<método> Notas de Java SE 2009 Dr. Manuel Mora T. 134/ 150 17. JDBC JDBC: Overview (sin usar GUI objects) • JDBC (Java Database Connectivity) API is used to interact with databases (in relational format). JDBC architecture can be used in two modes: • two-tier mode ( java + JDBC DBMS ) • three-tier mode ( java applet or html page java application server + JDBC DBMS ) • To use it, it will be required the following key elements: • a JDBC driver (it is unique for each type of database provider) • a DBMS tool • a set of Java instructions available in the packages: java.sql and javax.sql with the following key elements: •Classes • Class • Connection • Statement • PreparedStatement • ResultSet • SQLException • SQLWarning •Instructions • Class.forName( jdbc-driver ); • <ConnectionObj>= DriverManager.getConnection( url, user, psw ); • <StatementObj> = <ConnectionObj>.createStatement(type-result, type-concurreny, typecursor ); • <StatementObj>.executeUpdate( SQL-expression ); /* insert, update, delete • Boolean status = <StatementObj>.execute(SQL-expression); /* It can be select, insert, update or delete, where the returned result is true if it is a select (to use .getResultset(); ) • <PreparedStatementObj>.<ConnectionObj>.prepareStatement( SQL-statement); • <PreparedStatementObj>.setInt(#param, value); • <PreparedStatementObj>.setString(#param, value); • <PreparedStatementObj>.setFloat(#param, value); •<PreparedStatementObj>.executeUpdate(); • <ResultSet> = <PreparedStatementObj>.executeQuery(); • <ResultSet> = <StatementObj>.executeQuery( SQL-query ); • <ResultSet>.next(); /* .previous(); .first(); .last(); .beforeFirst(); .afterLast(); /* return a boolean • <ResultSet>.relative(#rows); /* .absolute(#rows); • <intVar> = <ResultSet>.getRow(); • <intVar> = <ResultSet>.getInt( #col OR name-col ); • <StringVar>= <ResultSet>.getString( #col OR name-col ); • <FloatVar>= <ResultSet>.getFloat( #col OR name-col ); • <ResultSet>.updateInt( #col OR name-col); • <ResultSet>.updateString( #col OR name-col); • <ResultSet>.updateFloat( #col OR name-col); • <ResultSet>.updateRow(); • <ResultSet>.deleteRow(); • <ResultSet>.insertRow(); Notas de Java SE 2009 Dr. Manuel Mora T. 135/ 150 17. JDBC JDBC: Overview (usando GUI objects) • JDBC (Java Database Connectivity) API can be used through Netbeans GUI objects. To use them, it will be required the following key elements: • a JDBC driver (it is unique for each type of database provider) • a DBMS tool • a set of Java instructions available in the palette packages: Java Persistence and Swing Controls. It can be possible also to use normal instructions contained in packages: java.sql and javax.sql reported in the previous page. Java Persistence • Entity Class (from a Database) public class <Nombre-Entidad> implements Serializable { } • Entity Manager • Query • QueryResult Swing Controls (the main to be used are the following ones:) • JTable • JList • JComboBox • JTextField • JPasswordField Notas de Java SE 2009 Dr. Manuel Mora T. 136/ 150 17. JDBC JDBC: Main Steps (sin usar GUI objects) • Task #1. Load and register the MySQL Connector/J driver: import java.sql.*; public class LoadDriver { public static void main(String[] args) { try { Class.forName("com.mysql.jdbc.Driver"); } catch (Exception ex) { // handle the error } } } • Task #2. To establish a connection to database: import java.sql.*; Connection conn = null; String urlDB = “jdbc:mysql://localhost:3306/dbname”; /* update to the correct URL ! String userDB = “theusername”; String pswDB = “thepswDB”; ... try { conn = DriverManager.getConnection(urlDB, userDB, pswDB); // Do something with the Connection ... } catch (SQLException ex) { // handle any errors System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); System.out.println("VendorError: " + ex.getErrorCode()); } Notas de Java SE 2009 Dr. Manuel Mora T. 137/ 150 17. JDBC JDBC: Main Steps (sin usar GUI objects) • Task #3. Execute SQL SELECT statements: import java.sql.*; // conn is a Connection object already created ! Statement stmt = null; ResultSet rs = null; String SqlQueryExp = “SELECT …. FROM …. WHERE … “; /* resultSetType - a result set type; one of ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE, or ResultSet.TYPE_SCROLL_SENSITIVE resultSetConcurrency a concurrency type; one of ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE */ try { stmt = conn.createStatement(resultSetType, resultSetConcurrency); rs = stmt.executeQuery(SqlQueryExp"); // Now do something with the ResultSet rs .... } catch (SQLException ex) { // handle any errors System.out.println("SQLException: " + ex.getMessage()); System.out.println("SQLState: " + ex.getSQLState()); System.out.println("VendorError: " + ex.getErrorCode()); } finally { if (rs != null) { try { rs.close(); } catch (SQLException sqlEx) { } // ignore rs = null; } if (stmt != null) { try { stmt.close(); } catch (SQLException sqlEx) { } // ignore stmt = null; } } Notas de Java SE 2009 Dr. Manuel Mora T. 138/ 150