Manual de Programación Web III

Tamaño: px
Comenzar la demostración a partir de la página:

Download "Manual de Programación Web III"

Transcripción

1 Manual de Programación Web III V CICLO COMPUTACIÓN E INFORMÁTICA

2 Indice 1. Introduccion a java 2 2. Sintaxis del lenguaje java Programacion orientada a objetos con java Excepciones Colecciones Conectandose a base de datos Diseño gui con awt y swing Sockets 179 2

3 PROGRAMACIÓN WEB III INTRODUCCION A JAVA Historia Java surgió en 1991 cuando un grupo de ingenieros de Sun Microsystems trataron de diseñar un nuevo lenguaje de programación destinado a electrodomésticos. La reducida potencia de cálculo y memoria de los electrodomésticos llevó a desarrollar un lenguaje sencillo capaz de generar código de tamaño muy reducido. Debido a la existencia de distintos tipos de CPUs y a los continuos cambios, era importante conseguir una herramienta independiente del tipo de CPU utilizada. Desarrollaron un código neutro que no dependía del tipo de electrodoméstico, el cual se ejecutaba sobre una máquina hipotética o virtual denominada Java Virtual Machine (JVM). Era la JVM quien interpretaba el código neutro convirtiéndolo a código particular de la CPU utilizada. Esto permitía lo que luego se ha convertido en el principal lema del lenguaje: Write Once, Run Everywhere. A pesar de los esfuerzos realizados por sus creadores, ninguna empresa de electrodomésticos se interesó por el nuevo lenguaje. Como lenguaje de programación para computadores, Java se introdujo a finales de La clave fue la incorporación de un intérprete Java en la versión 2.0 del programa Netscape Navigator, produciendo una verdadera revolución en Internet. Java 1.1 apareció a principios de 1997, mejorando sustancialmente la primera versión del lenguaje. Java 1.2, más tarde rebautizado como Java 2, nació a finales de Al programar en Java no se parte de cero. Cualquier aplicación que se desarrolle se apoya en un gran número de clases preexistentes. Algunas de ellas hechas por el propio usuario, otras pueden ser comerciales, pero siempre hay un número muy importante de clases que forman parte del propio lenguaje (el API o Application Programming Interface de Java). Java incorpora en el propio lenguaje muchos aspectos que en cualquier otro lenguaje son extensiones propiedad de 3

4 empresas de software o fabricantes de ordenadores (threads, ejecución remota, componentes, seguridad, acceso a bases de datos, etc.). Por eso Java es un lenguaje de programación ideal porque incorpora todos estos conceptos de un modo estándar, mucho más sencillo y claro que con las citadas extensiones de otros lenguajes. Esto es consecuencia de haber sido diseñado más recientemente y por un único equipo. El principal objetivo del lenguaje Java es llegar a ser el nexo universal que conecte a los usuarios con la información, esté ésta situada en el ordenador local, en un servidor de Web, en una base de datos o en cualquier otro lugar. En conclusión java es un lenguaje originalmente desarrollado por un grupo de ingenieros de Sun, utilizado por Netscape posteriormente como base para Javascript. Si bien su uso se destaca en el Web, sirve para crear todo tipo de aplicaciones (locales, intranet o Internet). Qué es java? Java es un lenguaje de programación muy completo. La compañía Sun describe el lenguaje Java como simple, orientado a objetos, distribuido, interpretado, robusto, seguro, de arquitectura neutra, portable, de altas prestaciones, multitarea y dinámico. Los programas desarrollados en Java presentan diversas ventajas frente a los desarrollados en otros lenguajes como C/C++. La ejecución de programas en Java tiene muchas posibilidades: ejecución como aplicación independiente (Stand-alone Application), ejecución como applet, ejecución como servlet, etc. Un applet es una aplicación especial que se ejecuta dentro de un navegador o browser (por ejemplo Netscape Navigator o Internet Explorer) al cargar una página HTML desde un servidor Web. El applet se descarga desde el servidor y no requiere instalación en el ordenador donde se encuentra el browser. Un servlet es una aplicación sin interface gráfica que se ejecuta en un servidor de Internet. La ejecución como aplicación independiente es análoga a los programas desarrollados con otros lenguajes. 4

5 Además de incorporar la ejecución como Applet, Java permite fácilmente el desarrollo tanto de arquitecturas cliente-servidor como de aplicaciones distribuidas, consistentes en crear aplicaciones capaces de conectarse a otros ordenadores y ejecutar tareas en varios ordenadores simultáneamente, repartiendo por lo tanto el trabajo. Aunque también otros lenguajes de programación permiten crear aplicaciones de este tipo, Java incorpora en su propio API estas funcionalidades. Características: o o o o o Simple. Ofrece la funcionalidad de un lenguaje potente pero sin las características menos usadas y más confusas de éstos. El ejemplo más claro puede ser el recolector de basura, que evita que andemos preocupándonos de liberar memoria. Otro ejemplo podría ser la supresión de los punteros. Lenguaje de objetos. Por qué "de" objetos y no "orientado a" objetos? Por que, al contrario de otros lenguajes como C++, no es un lenguaje modificado para poder trabajar con objetos sino que es un lenguaje creado para trabajar con objetos desde cero. De hecho, TODO lo que hay en Java son objetos. Java soporta las tres características básicas de la orientación a objetos: encapsulación, herencia y polimorfismo. Distribuido. Proporciona las librerías y herramientas necesarias para que las aplicaciones puedan ser distribuidas. Se ha desarrollado con extensas capacidades de interconexión a red y soporta varios protocolos de red. Robusto. Realiza variadas comprobaciones tanto en tiempo de compilación como de ejecución. Entre ellas podemos mencionar la comprobación de tipos y la comprobación de límites de arrays. Portable. Esto no se refiere a la independencia de la plataforma, si no a la portabilidad en cuanto a desarrollo. Por ejemplo, los enteros son siempre enteros de 32 bits en complemento a 2, con independencia de la plataforma. 5

6 o o o Multiplataforma. Como mencionamos antes, no es necesario recompilar las aplicaciones Java para los distintos sistemas en que van a ser explotadas. Multihilo. Permite múltiples hilos de ejecución, es decir, muchas actividades simultáneas dentro del mismo programa. Las ventajas de esto son un mejor rendimiento interactivo (el usuario no percibe tanto la ocupación de la máquina) y un mejor comportamiento en tiempo real (aunque sea algo muy limitado por el sistema operativo). Dinámico. Cuando una aplicación se lanza, no se cargan todas las librerías que requiere, sino que la carga es bajo demanda. Las librerías nuevas o actualizadas no paralizarán las aplicaciones en funcionamiento. Plataformas de desarrollo El software de Java contempla 3 plataformas para el desarrollo de aplicaciones: o Java SE (Java Standard Edition) Es el conjunto de herramientas software que permite el desarrollo y la ejecución de programas Java destinados al lado cliente. Se le suele llamar SDK (Software Development Kit) o Kit de Desarrollo de Programas. Es gratuito y de libre distribución. Se puede descargar desde la página oficial de Sun Microsystems relacionada con Java Dentro de la plataforma Java SE, se incluye el compilador y la JVM (Java Virtual Machine) o Máquina virtual de Java. También se la conoce como Intérprete de Java. Cada plataforma tiene su propia versión. En la página de Java dentro de Sun puede descargarse el Java SE para Windows, Linux, Solaris, etc. Si se trabaja con sistemas operativos menos corrientes como MacOS de Apple, AIX de IBM, HP-UX de Hewlett-Packard, etc. o Java EE (Java Enterprise Edition) Plataforma del lenguaje Java destinada al desarrollo de aplicaciones empresariales estructuradas típicamente en tres capas: capa de presentación de datos, capa de lógica de negocio y capa de datos 6

7 persistentes (bases de datos). Se compone de un conjunto de estándares y bibliotecas Java que permiten la creación de las aplicaciones empresariales anteriormente citadas. Esta plataforma se utiliza sobre todo para programación en servidores. Sin conocer lo fundamental de Java SE, resulta inviable introducirse en Java EE. o Java ME (Java Micro Edition) Plataforma del lenguaje Java destinada al desarrollo de aplicaciones para pequeños dispositivos móviles de memoria limitada, poca capacidad de procesamiento y con interfaces gráficas limitadas. Típicamente teléfonos móviles, PDAs (Personal Assistent Digital), Pockets PCs, televisiones, relojes, sistemas de ayuda para automóviles, tarjetas, etc. Como en Java EE, la base para programar mediante Java ME, es Java SE. El Entorno De Desarrollo De Java Existen distintos programas comerciales que permiten desarrollar código Java. La compañía Sun, creadora de Java, distribuye gratuitamente el Kit de Desarrollo de Java (JDK). Se trata de un conjunto de programas y librerías que permiten desarrollar, compilar y ejecutar programas en Java. Incorpora además la posibilidad de ejecutar parcialmente el programa, deteniendo la ejecución en el punto deseado y estudiando en cada momento el valor de cada una de las variables (con el denominado Debugger). Cualquier programador con un mínimo de experiencia sabe que una parte muy importante (muchas veces la mayor parte) del tiempo destinado a la elaboración de un programa se destina a la detección y corrección de errores. Existe también una versión reducida del JDK, denominada JRE (Java Runtime Environment) destinada únicamente a ejecutar código Java (no permite compilar). Los IDEs (Integrated Development Environment), tal y como su nombre indica, son entornos de desarrollo integrados. En un mismo programa es posible escribir el código Java, compilarlo y ejecutarlo sin tener que cambiar de aplicación. Algunos incluyen una herramienta para realizar Debug gráficamente, frente a la versión que incorpora el JDK basada en la utilización de una consola 7

8 (denominada habitualmente ventana de comandos de MS-DOS, en Windows NT/95/98) bastante difícil y pesada de utilizar. Estos entornos integrados permiten desarrollar las aplicaciones de forma mucho más rápida, incorporando en muchos casos librerías con componentes ya desarrollados, los cuales se incorporan al proyecto o programa. Como inconvenientes se pueden señalar algunos fallos de compatibilidad entre plataformas, y ficheros resultantes de mayor tamaño que los basados en clases estándar. Algunos IDEs que podemos citar son: Netbeans, Jdeveloper, Eclipse y JCreator entre otros. Bytecodes Un programa C o C++ es totalmente ejecutable y eso hace que no sea independiente de la plataforma y que su tamaño normalmente se dispare ya que dentro del código final hay que incluir las librerías de la plataforma. Proceso de compilación de un programa C++ Los programas Java no son ejecutables, no se compilan como los programas en C o C++. En su lugar son interpretados por una aplicación conocida como la máquina virtual de Java (JVM). Gracias a ello no tienen porque incluir todo el código y librerías propias de cada sistema. 8

9 Previamente el código fuente en Java se tiene que precompilar generando un código (que no es directamente ejecutable) previo conocido como bytecode o J- code. Ese código (generado normalmente en archivos con extensión class) es el que es ejecutado por la máquina virtual de Java que interpreta las instrucciones de los bytecodes, ejecutando el código de la aplicación. El bytecode se puede ejecutar en cualquier plataforma, lo único que se requiere es que esa plataforma posea un intérprete adecuado (la máquina virtual de esa plataforma). La Java Virtual Machine La existencia de distintos tipos de procesadores y ordenadores llevó a los ingenieros de Sun a la conclusión de que era muy importante conseguir un software que no dependiera del tipo de procesador utilizado. Se planteó la necesidad de conseguir un código capaz de ejecutarse en cualquier tipo de máquina. Una vez compilado no debería ser necesaria ninguna modificación por el hecho de cambiar de procesador o de ejecutarlo en otra máquina. La clave consistió en desarrollar un código neutro el cual estuviera preparado para ser ejecutado sobre una máquina hipotética o virtual, denominada Java Virtual Machina (JVM). Es esta JVM quien interpreta este código neutro convirtiéndolo a código particular de la CPU utilizada. Se evita tener que realizar un programa diferente para cada CPU o plataforma. La JVM es el intérprete de Java. Ejecuta los bytecodes (ficheros compilados con extensión *.class) creados por el compilador de Java (javac.exe). Tiene numerosas opciones entre las que destaca la posibilidad de utilizar el denominado JIT (Just-In-Time Compiler), que puede mejorar entre 10 y 20 veces la velocidad de ejecución de un programa. La JVM, además es un programa muy pequeño y que se distribuye gratuitamente para prácticamente todos los sistemas operativos. A este método de ejecución de programas en tiempo real se le llama Just in Time (JIT). 9

10 Proceso de compilación de un programa Java Compilación y ejecución de código java Hay que entender que Java es estricto en cuanto a la interpretación de la programación orientada a objetos. Así, se sobrentiende que un archivo java crea una (y sólo) clase. Por eso al compilar se dice que lo que se está compilando es una clase. javac La compilación del código java se realiza mediante el programa javac incluido en el software de desarrollo de java. La forma de compilar es (desde la línea de comandos): javac archivo.java El resultado de esto es un archivo con el mismo nombre que el archivo java pero con la extensión class. Esto ya es el archivo con el código en forma de bytecodes. Es decir con el código precompilado. java Si la clase es ejecutable (sólo lo son si contienen el método main), el código se puede interpretar usando el programa java del kit de desarrollo. Sintaxis: java archivo.class El compilador Java es una de las herramientas de desarrollo incluidas en el JDK. Realiza un análisis de sintaxis del código escrito en los ficheros fuente de Java (con extensión *.java). Si no encuentra errores en el código 10

11 genera los ficheros compilados (con extensión *.class). En otro caso muestra la línea o líneas erróneas. En el JDK de Sun dicho compilador se llama javac.exe. Tiene numerosas opciones, algunas de las cuales varían de una versión a otra. Se aconseja consultar la documentación de la versión del JDK utilizada para obtener una información detallada de las distintas posibilidades. La compilación del código java se realiza mediante el programa javac incluido en el software de desarrollo de java. La forma de compilar es (desde la línea de comandos): javac archivo.java El resultado de esto es un archivo con el mismo nombre que el archivo java pero con la extensión class. Esto ya es el archivo con el código en forma de bytecodes. Es decir con el código precompilado. Si la clase es ejecutable (sólo lo son si contienen el método main), el código se puede interpretar usando el programa java del kit de desarrollo. Sintaxis: java archivo.class Estos comandos hay que escribirlos desde la línea de comandos de en la carpeta en la que se encuentre el programa. Pero antes hay que asegurarse de que los programas del kit de desarrollo son accesibles desde cualquier carpeta del sistema. Para ello hay que comprobar que la carpeta con los ejecutables del kit de desarrollo está incluida en la variable de entorno path. JAVA javac Java Byte-code java Environment Java VM.java.class Compilación de un programa Java 11

12 Estos comandos hay que escribirlos desde la línea de comandos en la carpeta en la que se encuentre el programa. Pero antes hay que asegurarse de que los programas del kit de desarrollo son accesibles desde cualquier carpeta del sistema. Para ello hay que comprobar que la carpeta con los ejecutables del kit de desarrollo está incluida en la variable de entorno path. Esto lo podemos comprobar escribiendo path en la línea de comandos. Si la carpeta del kit de desarrollo no está incluida, habrá que hacerlo. Para ello en Windows 2000, 2003 o XP: 1. Pulsar el botón derecho sobre Mi PC y elegir Propiedades 2. Ir al apartado Opciones avanzadas 3. Hacer clic sobre el botón Variables de entorno 4. Añadir a la lista de la variable PATH la ruta a la carpeta con los programas del JDK. 5. Añadir la variable CLASSPATH si es que no existe y el valor a asignarle seria un punto. Ejemplo de contenido de la variable PATH: PATH= C:\Archivos de programa\java\jdk1.6.0_06\bin; En negrita está señalada la ruta a la carpeta de ejecutables (carpeta bin) del kit de desarrollo. Está carpeta varía según la instalación del JDK Ejemplo de contenido de la variable CLASSPATH: CLASSPATH =.; Javadoc Javadoc es una herramienta muy interesante del kit de desarrollo de Java para generar automáticamente documentación Java. Genera documentación para paquetes completos o para archivos java. Su sintaxis básica es: javadoc archivo.java o paquete 12

13 El funcionamiento es el siguiente. Los comentarios que comienzan con los códigos /** se llaman comentarios de documento y serán utilizados por los programas de generación de documentación javadoc. Tipos de archivos java: Es la extensión de los archivos fuente del lenguaje java, ejem. bienvenido.java, Miapplet.java. class: El resultado de compilar un archivo fuente java es un archivo en bytecode con extensión class, ejem. bienvenido.class, Miapplet.class. El comando usado para compilar los arhivos con extensión java es javac y para su ejecución el comando java que vienen incluidos en el JDK (Java Development Kit) de Sun Microsystems. jar/zip: Las clases desarrolladas en java suelen por lo general guardarse en estos tipos de archivos comprimidos. Ejercicio //archivo con el nombre Bienvenido.java class Bienvenido { public static void main(string [] args) { System.out.println("Bienvenido a Java!"); Grabar el archivo en la carpeta Demos01 con el nombre Bienvenido.java luego compilar y ejecutar el programa anterior, con los programas javac y java respectivamente. javac Bienvenido.java java Bienvenido Línea 1: es un simple comentario de tipo línea en el que hemos colocado el nombre del fichero. El compilador ignorará todo lo que va desde los caracteres // hasta el final de la línea. Los comentarios son de mucha utilidad, tanto para otras personas que tengan que revisar el código, como para nosotros mismos en futuras revisiones. 13

14 Línea 2: declara el nombre de la clase. Usamos la palabra reservada class seguida del nombre que queremos darle a nuestra clase, en este caso es Bienvenido. Ya sabemos que Java es un lenguaje orientado a objetos, por tanto, nuestro programa ha de ser definido como una clase. Por convención, las clases Java se definen con la primera letra en mayúsculas. Línea 3: declara el método principal (main) utilizando el modificador de acceso public (acceso publico), el modificador static y el tipo que retorna es void (nada) y como parámetro recibe un arreglo de Strings. Linea 4: se invoca al método println(param) que Escribe el valor de param y luego se produce un cambio de línea que equivale a pulsar retornar, al final de toda sentencia se debe colocar el punto y coma (;) que indica el fin de la sentencia. Linea 5 y 6: Se termina el cuerpo del método principal y de la clase. 14

15 SINTAXIS DEL LENGUAJE JAVA Consideraciones Todo el código fuente Java se escriben en documentos de texto con extensión.java. Al ser un lenguaje para Internet, la codificación de texto debía permitir a todos los programadores de cualquier idioma escribir ese código. Eso significa que Java es compatible con la codificación Unicode. En la práctica significa que los programadores que usen lenguajes distintos del inglés no tendrán problemas para escribir símbolos de su idioma. Y esto se puede extender para nombres de clase, variables, etc. La codificación Unicode2 usa 16 bits (2 bytes por carácter) e incluye la mayoría de los códigos del mundo. Los archivos con código fuente en Java deben guardarse con la extensión.java. Como se ha comentado cualquier editor de texto se puede usar para codificar un archivo. En java el código es sensitivo (case sensitive) es decir existe diferencias entre mayúsculas y minúsculas. Cuando se programa en Java, se coloca todo el código en métodos. Cada línea de código debe terminar con punto y coma (;) que indica el fin de la sentencia. Los comentarios; si son de una línea deben comenzar con: // y si ocupan más de una línea deben comenzar con /* y terminar con */ A veces se marcan bloques de código, los cuales comienza con { y terminan con 15

16 Ejercicio public class app004 { public static void main(string[] args) { //Comentario de una línea System.out.println( Programacion Web III! ); /* Comentarios de Varias Lineas */ Sidem Carlos Enrique Este código escribe Programacion Web III! en la pantalla. El archivo debería llamarse app004.java ya que esa es la clase pública. El resto define el método main que es el que se ejecutará al lanzarse la aplicación. Ese método utiliza la instrucción que escribe en pantalla; y también se utilizan los comentarios de una y varias líneas. Comentarios En java al igual que en otros lenguajes existen los comentarios y estos pueden ser considerados como un caso especial dentro de los elementos de la sintaxis del lenguaje, ya que aunque estos sean reconocidos por el compilador, éste los ignora. En Java existen tres tipos de comentarios. // Comentario de una línea. /* Comentario de */ Varias líneas. /** Comentario de Documentación 16

17 * Esta aplicación realiza lo siguiente: Carlos Durand Flores 1.0 */ Los dos primeros tipos de comentarios son los que todo programador conoce y se utilizan del mismo modo. Los comentarios de documentación, indican que ese comentario ha de ser colocado en la documentación que se genera automáticamente cuando se utiliza la herramienta de Java, javadoc. Dichos comentarios sirven como descripción del elemento declarado permitiendo generar una documentación de nuestras clases escrita al mismo tiempo que se genera el código. Los comentarios javadoc comienzan con el símbolo /** y terminan con */ Cada línea javadoc se inicia con un símbolo de asterisco. Dentro se puede incluir cualquier texto. Incluso se pueden utilizar códigos HTML para que al generar la documentación se tenga en cuenta el código HTML indicado. En este tipo de comentario para documentación, se permite la introducción de algunos tokens, palabras clave o etiquetas especiales que harán que la información que les sigue aparezca de forma diferente al resto en la documentación, estos comienzan con el y pueden ser: o o o o o Tras esa palabra se indica el autor del Tras lo cual sigue el número de versión de la Tras esta palabra se indica una referencia a otro código Java relacionado con Indica desde cuándo esta disponible este Palabra a la que no sigue ningún otro texto en la línea y que indica que esta clase o método esta obsoleta u Indica las excepciones que pueden lanzarse en ese código. 17

18 o Palabra a la que le sigue texto qué describe a los parámetros que requiere el código para su utilización (el código en este caso es un método de clase). Cada parámetro se coloca en una distinta, por lo que puede haber Para el mismo Tras esta palabra se describe los valores que devuelve el código (el código en este caso es un método de clase) El código javadoc hay que colocarle en tres sitios distintos dentro del código java de la aplicación: 1. Al principio del código de la clase (antes de cualquier código Java). En esta zona se colocan comentarios generales sobre la clase o interfaz que se crea mediante el código Java. Dentro de estos comentarios se pueden utilizar 2. Delante de cada método. Los métodos describen las cosas que puede realizar una clase. Delante de cada método los comentarios javadoc se usan para describir al método en concreto. Además de los comentarios, en esta zona se pueden incluir @since 3. Delante de cada atributo. Se describe para qué sirve cada atributo en cada clase. Puede poseer las Ejercicio /** Esto es un comentario para probar el javadoc * este texto aparecerá en el archivo HTML generado. * <strong>realizado en agosto 2008</strong> * Carlos Durand 1.0 */ 18

19 public class app005 { //Este comentario no aparecerá en el javadoc /** Este método contiene el código ejecutable de la clase * args Lista de argumentos de la línea de comandos void */ public static void main(string args[]){ System.out.println(" Mi aplicación app005! "); Tras ejecutar la aplicación javadoc, aparece como resultado una página web donde aparecerá la documentación de nuestra clase implementada.. Bloques y ámbitos Bloques Al igual que C, Java utiliza las llaves ({ la primera de inicio y la otra de fin de bloque) para determinar los bloques dentro de un programa. Todo lo que se encuentra entre estas dos llaves se considera un bloque. Los bloques son parte de la sintaxis del lenguaje. Los bloques pueden y suelen anidarse; utilizándose la sangría para clarificar el contenido de un bloque. De este modo, el bloque más externo se sitúa al margen izquierdo del fichero de código fuente, y cada vez que se anida un bloque se indenta (sangra) el texto que lo contienen un número determinado de columnas, normalmente tres o cuatro. El sangrado no tiene ninguna utilidad para el compilador, pero sin ella la lectura del código por parte del programador es casi imposible. 19

20 Ámbitos Los bloques además, definen los ámbitos de las variables. El ámbito se refiere a la longevidad de las variables. Una variable existe sólo dentro del bloque donde ha sido declarada, eliminándola el compilador una vez que se sale de dicho bloque. Esto es cierto para todos los tipos de datos de Java. Si el dato es un objeto, y su clase tiene un destructor asociado (distinto al destructor por defecto, que es interno y Java lo maneja por sí solo) este es invocado al salir la variable de ámbito. Cuando una variable sale de ámbito, es eliminada y la memoria que ésta ocupaba es liberada por el recolector de basura (garbage collector). Identificadores Los identificadores sirven para nombrar variables, propiedades, métodos, funciones, clases, interfaces y objetos; o cualquier entidad que el programador necesite identificar para poder usar. Estos identificadores sirven de mucho al programador, si éste les da sentido. En Java, un identificador comienza con una letra, un subrayado (_) o un símbolo de dólar ($). Los siguientes caracteres pueden ser letras o dígitos. No existe una longitud máxima y se distinguen las mayúsculas de las minúsculas, de este modo el compilador puede identificarlos unívocamente. Por ejemplo, si vamos a implementar una clase para manejo del fichero de clientes, sería recomendable que la misma se llamara algo así como ClientManager, o ManejadordeCliente, no tendría sentido, aunque es totalmente válido llamarla Aj23. Existe una serie de palabras reservadas las cuales tienen un significado especial para Java y por lo tanto no se pueden utilizar como nombres identificadores. Dichas palabras son: 20

21 abstract boolean break byte case catch char class const* continue default do double else extends final finally float for goto* if implements import instanceof int interface long native new null package private protected public return short static super switch synchronized this throw throws transient try void volatile while byvalue threadsafe false true (*) Son palabras reservadas, pero no se utilizan en la actual implementación del lenguaje Java. Además, el lenguaje se reserva unas cuantas palabras más, pero que hasta ahora no tienen un cometido específico. Son: cast future generic inner operator rest Var outer Serían identificadores válidos: nombre_usuario Nombre_Usuario _variable_del_sistema $transaccion y su uso sería, por ejemplo: int contador_principal; char _lista_de_ficheros; float $cantidad_en_ptas; Tipos de datos primitivos Estos tipos de datos simples o también llamados tipos primitivos, permiten declarar un variable de tipo primitiva que reserva el espacio de memoria necesario. 21

22 <tipo> <idetificador1> [= <valor1>] [, <identificadorn> [= <valorn>]]; O bien, con asignación múltiple: <tipo> <idetificador1>,...,<identificadorn> = <valor>; Byte Entero muy pequeño. Short Entero Corto. Int Entero normal. Long Entero largo. Char Carácter. Float Número real de precisión simple. Double Número real de doble precisión. Boolean Valor lógico. Void Tipo Vació. De no asignarse un valor de inicio, el compilador por defecto asignará uno. Tipos Precisión Valor Por Defecto Byte 8 bits 0 Short 16 bits 0 Int 32 bits 0 Long 64 bits 0 Char 16 bits \u0000 Float 32 bits +0.0f Double 64 bits +0.0d Boolean - false Enteros Como en otros lenguajes, Java maneja el tipo de datos entero, y con distintos tamaños y capacidades. Es uno de los tipos que la máquina virtual de Java maneja de forma directa. Cada implementación de la 22

23 máquina virtual debe cumplir con una serie de reglas de manipulación de enteros (y otros tipos primitivos) que aseguran que nuestros programas Java se comporten de la misma forma en distintas plataformas. Esto asegura la portabilidad de Java. En otros lenguajes, como por ejemplo C o C++, el tamaño y capacidades de los enteros, varía de sistema operativo a sistema operativo, y aún dentro de la misma plataforma, de fabricante de compilador a otro. Eso ha provocado que la portabilidad de muchos programas C/C++ se haya visto dificultada por este estado de cosas. Si bien se ha avanzado mucho en solucionar el problema, los diseñadores del lenguaje Java se plantearon desde el comienzo solucionarlo. Para eso adoptaron un formato estándar de los tipos primitivos para todo Java, independiente de la máquina donde se ejecute. Hay cuatro tipos enteros en Java: byte Valores que pueden tener entre -128 a +127, y ocupan como era de esperarse un byte (8 bits) en memoria short Valores entre a 32767, que ocupan 2 bytes (16 bits) en memoria int El tipo entero normal, con un rango de valores de entre a , que ocupa 4 bytes (32 bits) en memoria long El tamaño más grande de entero que maneje Java, con valores entre hasta Ocupan 8 bytes (64 bits). Algunos ejemplos de declaraciones: byte cantidadahorrada; short cantidadclientes; int cantidaddeudas; 23

24 long deudaexterna; Debemos tratar ahora el tema de escribir, en el código, valores correspondientes a los tipos enteros. Los literales enteros (recordemos que esto incluye a los byte y a los short, así como los int y long), se escriben en dígitos decimales, octales o hexadecimales. Espero que Ud. esté familiarizado con los primeros (en caso contrario, deberá repasar su cultura general). Como expresiones decimales válidas tenemos: Las expresiones octales (en base 8), comienzan con un dígito 0 (cero), y las hexadecimales (en base 16, con dígitos 0-9 y a-f o A-F) con un 0x o 0X (Cero y equis). Las siguientes expresiones entonces son equivalentes: x0c 0x0C Cuando un literal entero termina con l o L (letra ele), es un entero largo (del tipo long). En caso contrario, se toma de tipo int (entero simple). Una constante int se puede asignar a short o byte directamente, si es posible acomodarla en ese tipo. Podemos declarar una variable y darle un valor inicial, en la misma sentencia: long numerogrande = L; El valor a asignar se coloca luego de un signo de igual. Es común poner un valor inicial a una variable local a un método. En caso de no hacerlo, si usamos la variable sin valor inicial, el compilador nos advierte del problema. El siguiente código, inserto en un método, no compilaría: int k; k=k+1; 24

25 Pueden declararse varias variables en la misma sentencia, y hasta asignárseles valores: int x, y; int xinicial = 0, yinicial = 0; Como el compilador no toma como especiales los cambios de línea, podemos escribir este tipo de declaraciones de la forma: int xinicial = 0, yinicial = 0, zinicial = 0; Los valores del tipo byte o short, se inicializan de manera similar: byte unocteto = 7; short unvalor = 2300; Notemos que no hizo falta declarar al 7 como byte, o al 2300 como entero corto. El compilador se encarga de tomarlos como valores byte y short, respectivamente. Java no solamente especifica la forma de tratar a los enteros, sino también cómo se graban o serializan en algún medio externo. Esto hace posible que lo grabemos en un archivo como entero, luego lo podamos recuperar de la misma forma, aún desde otra plataforma. Esto no es así de fácil en otros lenguajes: muchos compiladores C graban enteros de una forma en la plataforma Motorola, y de otra forma en plataforma Intel, aún cuando sean del mismo tamaño. Los de formato Intel, se graban con el byte menos significativo primero, y en el formato Motorola, se graban en orden inverso al de Intel. Números en coma flotante En Java, como en otros lenguajes, se manejan también números reales, en los formatos de punto flotante. Estos números no son enteros, tienen distinta precisión, y su rango de valores es mayor. Se guardan como los enteros, en formato binario, así que su representación decimal es aproximada (en cuanto a la parte no entera). 25

26 float Pueden albergar valores desde -3.4E38 hasta +3.4E38, ocupando 4 bytes en memoria. Tienen una precisión aproximada de 7 dígitos. double Contienen valores desde -1.7E308 hasta +1.7E308, consumiendo 8 bytes en la memoria. La precisión aproximada es de 17 dígitos. El menor valor almacenable está cercano a los E-324. Las operaciones sobre los valores de punto flotante, siguen las reglas de estándard IEEE 754. Notamos que estos valores pueden manejar un exponente en base 10. Valores válidos son: f 99.10F Los dos primeros se asumen de tipo double, mientras los segundos, al terminar en f o F, el compilador los procesa como del tipo float. El separador decimal es el punto. En caso de necesitar expresar un exponente en base 10, se usa la letra E seguida del exponente: 314e E1 Para declarar variables de tipo flotante, se sigue la misma convención que en las variables de tipo entero: double valorreal; double deuda = 1.496E8; float sueldo = 1.2E-2f; Como antes, podemos declarar más de una variable en la misma sentencia: float valor1 = 190.2f, 26

27 Booleanos valor2 = 192.3f; Los valores booleanos (o lógicos) sirven para indicar si algo es verdadero (true) o falso (false). En C se puede utilizar cualquier valor lógico como si fuera un número; así verdadero es el valor -1 y falso el 0. Eso no es posible en Java. Si a un valor booleano no se le da un valor inicial, se toma como valor inicial el valor false. Por otro lado, a diferencia del lenguaje C, no se pueden en Java asignar números a una variable booleana (en C, el valor false se asocia al número 0, y cualquier valor distinto de cero se asocia a true). Caracteres Los valores de tipo carácter sirven para almacenar símbolos de escritura (en Java se puede almacenar cualquier código Unicode). Los valores Unicode son los que Java utiliza para los caracteres. Ejemplo: char letra; letra= C ; //Los caracteres van entre comillas letra=67; //El código Unicode de la C es el 67. Esta línea //hace lo mismo que la anterior Cadena de caracteres Más conocidas por el nombre de Strings, no es un tipo primitivo de dato: es en realidad una clase, la clase String. Sin embargo, se pueden escribir constantes de este tipo, encerrándolas entre comillas dobles. Pueden contener todo tipo de caracteres, pudiendo ser algunas secuencias 'escape' como las vistas más arriba: "Hola, mundo\n" "Esta frase tiene \"comillas dobles\" y \'comillas simples\'" 27

28 Variables La doble comilla inicial y la final de un String deben estar en la misma línea del código fuente. Como hemos visto en algunos ejemplos, el operador + sirve para concatenar strings. Si uno de los dos operandos del + no es un String, lo convierte automáticamente a una cadena de caracteres. Una variable es un nombre que contiene un valor que puede cambiar a lo largo del programa es decir representan direcciones de memoria en las que podemos alojar temporalmente la información que necesitemos, y por otro, nos ofrecen la facilidad de referirnos a ellas mediante un nombre. Las variables son los contenedores de los datos que utiliza un programa. Cada variable ocupa un espacio en la memoria RAM del ordenador para almacenar un dato determinado. Una declaración de variable se compone de dos partes: su tipo y su nombre. Adicionalmente puede indicarse un valor para su inicialización. El tipo de la variable determina los valores que puede contener y las operaciones que se podrán realizar con ella. Según el tipo de información que contienen pueden ser variables de tipos primitivos o variables de referencia. Las variables tienen un nombre (un identificador) que sólo puede contener letras, números y el carácter de subrayado (también vale el símbolo $). El nombre puede contener cualquier carácter Unicode. Desde el punto de vista del papel que desempeñan, las variables pueden ser: Variable miembro de una clase: Se definen dentro de la clase y fuera de cualquier método. Variables locales: Se definen dentro de un método o, más en general, dentro de cualquier bloque entre llaves ({ ). Se crean dentro del bloque y se destruyen al finalizar dicho bloque. Declaración de variables 28

29 Antes de poder utilizar una variable, ésta se debe declarar. Lo cual se debe hacer de esta forma: TipoDeDato NombreVariable; Donde tipo es el tipo de datos que almacenará la variable (texto, números enteros,...) y nombrevariable es el nombre con el que se conocerá la variable. Ejemplo: int dias; boolean decision; También se puede hacer que la variable tome un valor inicial al declarar: int dias=365; Y también se puede declarar más de una variable a la vez: int dias=365, anio=23, semanas; Al declarar una variable se puede incluso utilizar una expresión: int a=13, b=18; int c=a+b; Alcance o ámbito Se denomina visibilidad, ámbito o alcance de una variable, a la parte de una aplicación en la que dicha variable es accesible. En otras palabras, la parte en la cual puede usarse dicha variable es decir hace referencia a la duración de una variable. Como norma general, podemos decir que las variables declaradas dentro de un bloque (entre llaves) son visibles y existen dentro de ese bloque. Por ejemplo, las variables declaradas al principio de una función existen mientras se ejecute la función, las declaradas dentro de un bloque if sólo serán accesibles y válidas dentro de dicho bloque y las variables miembro de una clase son válidas mientras existe el objeto. 29

30 En el ejemplo: if(z>1) { int x=12; System.out.println(x); //Error Existe un error, porque la variable se usa fuera del bloque en el que se creo. Eso no es posible, porque una variable tiene como ámbito el bloque de código en el que fue creada (salvo que sea una propiedad de un objeto). Variables Miembro Las variables miembro de una clase declarada como pública (public), serán accesibles mediante una referencia a un objeto de dicha clase usando el operador punto. Por su parte, las declaradas como privadas (private) no son accesibles desde otras clases. Las funciones miembro de una clase tienen acceso directo a todas las variables miembro de la clase sin necesidad de anteponer el nombre de un objeto de la clase. Sin embargo, las funciones miembro de una clase B derivada de otra A, tienen acceso a todas las variables miembro de A declaradas como públicas o protegidas (protected), pero no a las declaradas como privadas. Una clase hija sólo puede acceder directamente a las variables y función miembro de su clase padre declaradas como públicas o protegidas. Otra característica del lenguaje Java consiste en que es posible declarar una variable dentro de un bloque con el mismo nombre que una variable miembro, pero no con el nombre de otra variable local que ya existiera. La variable declarada dentro del bloque oculta a la variable miembro en ese bloque. Para acceder a la variable miembro oculta sería necesario que usáramos el operador this. 30

31 Sintaxis: [modificador] <Tipo> <nombredevariable> [= <inicializador>]; Convenciones y nomenclatura Con respecto a los nombres de variables, las reglas del lenguaje Java son muy amplias y permiten mucha libertad, pero es habitual seguir ciertas normas que faciliten la lectura y el mantenimiento de los programas. Por convención, se recomienda seguir las siguientes reglas: o o o o o Normalmente se emplean nombres con minúsculas salvo las excepciones que se enumeran en los siguientes puntos. En los nombres que se componen de varias palabras es aconsejable colocar una detrás de otra poniendo en mayúscula la primera letra de cada palabra. Los nombres de las clases y las interfaces empiezan siempre por mayúscula. Los nombres de objetos, métodos y variables empiezan siempre por minúscula. Los nombres de las variables finales (las constantes) se definen siempre con mayúsculas. Ejercicio # class Circunferencia { // Es una clase private final double PI = ; // Es una variable final private double elradio; // Es una variable miembro de la clase public void establecerradio(double radio) { // Son un método y una variable local elradio = radio; public double calcularlongitud() { // Es un método 31

32 return (2 * PI * elradio); Modificadores Los modificadores son elementos del lenguaje que se colocan delante de la definición de variables locales, dato miembro, métodos o clases y que alteran o condicionan el significado del elemento. Dentro de este grupo de modificadores tenemos un subgrupo denominado modificadores de acceso. Modificadores de Acceso public (Acceso libre) El campo es accesible de forma general sin restricciones. Significa que toda definición será accesible de cualquier punto, ya sea un método, campo o clase; Es decir indica que el elemento puede ser utilizado dentro de la clase, dentro de las clases descendientes y desde cualquier objeto de la clase. protected (Clases Heredadas y misma Clase) El campo es accesible desde cualquier subclase (tanto dentro como fuera del paquete) y a todo método dentro del paquete. Es decir indica que el elemento puede ser utilizado dentro de la clase, dentro de las clases descendientes, mas no desde un objeto de la clase. private (Solo en la misma Clase) El calificador private indica que dicho componente será accesible únicamente dentro de la Clase en cuestión, si se intenta accesar cualquier elemento de este tipo dentro de otra Clase será generado un error de compilación. El calificador private suele utilizarse en Clases que serán modificadas continuamente, esto permite evitar futuros quebrantos en otras Clases como fue mencionado al inicio. default (Clase en Librería y misma Clase) 32

33 Tambien denominado Package o tambien denominado Friendly, El campo es accesible a todos los métodos dentro del paquete. Es el acceso por defecto. Cuando no es empleado ninguno de los calificadores de acceso mencionados anteriormente los elementos son considerados amigables, esto implica que todo campo/método carente de calificador será accesible dentro de todas Clases pertenecientes a su misma librería ("package"). Modificadores static Una de los posibles usos del modificador static es compartir el valor de una variable miembro entre objetos de una misma clase. Si declaramos una variable miembro de una clase, todos los objetos que declaremos basandonos en esa clase compartiran el valor de aquellas variables a las que se les haya aplicado el modificador static, y se podrá modificar el valor de este desde todas. Un caso en el que nos podría ser muy util este modificador, es en una clase que nos diga la cantidad de objetos que se han creado basandose en ella. Podemos escribir una línea de código en el constructor que incremente la variable contador con el modificador static, y así cada vez que se declare un objeto el contador se incrementará. Desde cualquier objeto podremos consultar el valor del contador. El código sería algo así. class Clase { static int contador; Clase() { contador++; int getcontador() { return contador; class Codigo { 33

34 public static void main(string[] args) { Clase uno = new Clase(); Clase dos = new Clase(); Clase tres = new Clase(); Clase cuatro = new Clase(); System.out.println("Hemos declarado" + uno.getcontador() + " objetos."); Esto tiene varias ventajas, porque además de ahorrarnos algunas posiciones de memoria (porque todos objetos comparten la misma) podemos crear variables compartidas, cosa que abre la puerta a diversas posibilidades de uso. final El modificador final se aplica a clases, métodos y variables. El significado de final varia de contexto a contexto, pero la idea en si es la misma, la característica no puede ser cambiada. Esto quiere decir que de una clase final no se puede derivar otra clase, una variable final no puede ser modificada una vez que se le ha asignado el valor y un método final no puede ser sobreescrito. Aunque una variable final no puede ser cambiada, su contenido puede ser modificado. Si esta variable apunta a un objeto, es perfectamente válido modificar las propiedades del objeto. abstract El modificador abstract puede ser aplicado a clases y métodos. Una clase que es abstracta no puede ser instanciada (esto es, no se puede llamar a su constructor). Las clases abstractas se pueden utilizar como mecanismo para trasladar la implementación de los métodos a la subclase. De esta forma, para poder utilizar una clase abstracta se tiene que derivar y se tienen que implementar los métodos abstractos definidos en ellas. El compilador obligará a implementar todos los métodos abstractos de la clase o declarar la clase derivada abstracta. Si una clase tiene uno o más métodos abstractos el compilador insiste en que se debe declarar 34

35 abstracta. También debe ser abstracta la clase si hereda uno o más métodos abstractos para el cual no provee implementación o si la clase declara una interfase pero no proporciona implementaciones para cada uno de sus métodos. native Este modificador solo puede referirse a métodos, indica que el cuerpo de un método se encuentra fuera de la máquina virtual de Java, en una librería. El código nativo esta escrito en otro lenguaje de programación, típicamente C o C++ y compilado para una sola plataforma por lo que la independencia de plataforma de Java es violada cuando utilizamos este tipo de métodos. transient El modificador transient es solo aplicado a variables. Una variable transient no es almacenada como parte del estado persistente de su objeto. Muchos objetos que son declarados con interfases Serializable o Externalizable pueden tener su estado serializado y escribir a destinos fuera de la máquina virtual. Esto se logra pasando el objeto a el método writeobject() de la clase ObjectOutputStream. Si el objeto es pasado a un FileOutputStream, entonces el estado del objeto es escrito en un fichero. Si el objeto es pasado a un socket OutputStream, entonces el estado del objeto será escrito en una red. En ambos casos el objeto puede ser reconstruido leyendo de un ObjectInputStream. Cuando hay cierta información que no se desea enviar como parte del objeto, como puede ser cierta información delicada que quizás por razones de seguridad no deben ser enviadas a través de un canal inseguro (una contraseña), se declara transient y esta no es escrita durante la serialización. synchronized Este modificador es utilizado para controlar el acceso a código crítico en programas de hilado múltiple. Es casi imprescindible su uso cuando 35

36 utilizamos hilado múltiple y debemos acceder a propiedades o recursos desde varios hilos a la vez. volatile Solo las variables pueden ser declaradas volatile. Esto quiere decir que pueden ser modificadas de forma asincrónica para que el compilador tome las precauciones necesarias. Este tipo de variables tiene especial interés para los ambientes con varios procesadores ya que cuando un hilo modifica una variable de un objeto, este puede tener una copia local de la variable y modificar esta. El problema surge cuando otro hilo lee la variable y el valor recibido es el de la variable local al hilo. Esta puede diferir de la variable local del otro hilo e inclusive de la variable almacenada en una suerte de "memoria principal". Al especificar la variable como volatile se le indica a el compilador que la variable debe ser leída y escrita directamente de la "memoria principal" cada vez que se necesita evitando tener copias locales distintas. Características No todos los modificadores pueden ser aplicados a todas las características. Las clases de nivel superior no pueden ser protegidas y los métodos no pueden ser transient. En cambio la palabra clave static es tan general que se puede aplicar hasta en bloques de código flotantes. La siguiente tabla muestra las posibles combinaciones entre características y modificadores: Modificador Clase Variable Método Constructor Bloque flotante public yes yes yes yes no protected no yes yes yes no default yes yes yes yes yes private no yes yes yes no final yes yes yes no no abstract yes no yes no no static no yes yes no yes native no no yes no no transient no yes no no no volatile no yes no no no synchronized no no yes no yes 36

37 Constantes Constantes Literales Por su parte, las constantes literales son representaciones literales de datos en el código fuente. Estos valores se emplean para inicializar variables o para usarlas en expresiones en las que se requieren valores constantes. Las constantes literales pueden usarse para referirse explícitamente a uno de los tipos siguientes: int, long, float, double, boolean, char, String y null. En caso de que necesitáramos representar un tipo primitivo distinto de los indicados, podríamos hacer una conversión explícita al tipo deseado. Por otra parte, los objetos no pueden ser representados mediante estas constantes, y por tanto, no existen constantes literales de tipo de referencia. Constantes Enteras Las constantes enteras se representan por un valor que está formado sólo por dígitos numéricos y no tienen la coma decimal. Si el número no comienza por cero, representa un número decimal (en base 10). Para representar constantes de tipo long se emplea el mismo método pero añadiendo al final la letra L. Está permitido el empleo de la letra L en minúsculas, pero no debe usarse ya que puede confundirse con el número uno. Además de representaciones en formato decimal, se pueden representar constantes en los formatos octal y hexadecimal. Las constantes octales se representan anteponiendo un cero al propio número, que además, sólo podrá estar formado por los dígitos del 0 al 7. Por su parte, las constantes hexadecimales se representan anteponiendo 0x o 0X y permitiendo que los dígitos del número puedan ser del 0 al 9 y las letras de la A a la F (en mayúsculas o minúsculas). Las constantes octales y hexadecimales son de tipo entero a menos que estén seguidas por la letra L, en cuyo caso serían de tipo long. 37

38 int a = 1002; // Tipo int long b = 1002L; // Tipo long int c = 053; // Tipo int en octal int d = 053L; // Tipo long en octal int e = 0X002B ; // Tipo int en hexadecimal int f = 0X002BL; // Tipo long en hexadecimal El tipo char es un tipo entero, no obstante se trata de un tipo especial pensado para almacenar caracteres Unicode. Estos últimos son similares a los caracteres ASCII en que están pensados para almacenar símbolos, números y caracteres. Sin embargo, el rango del tipo char es mucho mayor porque permite representar caracteres de casi todos los idiomas del mundo. Las constantes literales de tipo char pueden representarse de dos formas distintas: Encerrando un único carácter entre comillas simples. Utilizando una secuencia de escape, que es muy útil para representar caracteres que no pueden escribirse mediante el teclado. La secuencia de escape se representa por una barra inclinada inversa (\) seguida de un número octal de tres dígitos, o bien por la barra seguida de la letra u y de un número hexadecimal de cuatro dígitos. La secuencia de escape también debe ir encerrada entre comillas simples. También existe una serie de secuencias de escape especiales que se utilizan para representar algunos de los caracteres ASCII más comunes. En la siguiente tabla se relacionan todos. Carácter Significado \n Nueva Línea \t Tabulador \r Retroceso de Carro \f Comienzo de Pagina \b Borrado a la Izquierda \\ El Carácter \ \ El Carácter \ El Carácter 38

39 Constantes De Coma Flotante Se expresan mediante un valor numérico que incluya al menos una posición decimal. A menos que se indique otra cosa, las constantes de coma flotante serán de tipo double. Para denotar que la constante sea de tipo float es necesario posponer la letra f o F. Por claridad, también pueden expresarse las constantes de tipo double posponiendo la letra d o D al número. Este tipo de constantes también pueden expresarse mediante la notación exponencial, que define un número en dos partes: la mantisa y el exponente. La mantisa es un número en coma flotante con un dígito significativo y cierto número de decimales. El exponente es un número que representa la potencia de 10 que multiplica a la mantisa. Entre la mantisa y el exponente se debe poner la letra e o E. double a = 123.4; // Tipo double float b = 123.4F; // Tipo float double c = 4.502e-12; // Tipo double en notación exponencial. Constantes De Cadena Las constantes de cadena se representan por una secuencia de caracteres encerrados entre comillas dobles. Dentro de ellas se pueden incluir las secuencias de escape que antes mencionamos. Veamos algunos ejemplos: String a = Texto simple ; // Texto simple String b = Esta es la letra \u0041 ; // Usando una secuencia de escape para la letra A String c = El proceso ha terminado.\npulse una tecla ; // Texto en dos líneas Constantes Booleanas Existen dos: true y false. Al contrario que en otros lenguajes de programación, ninguna de estas constantes puede ser representada mediante un valor entero usando como criterio la igualdad a cero. 39

40 Constante null Existe una constante nula (null) que podemos usarla para representar el valor null. Operadores Los datos se manipulan muchas veces utilizando operaciones con ellos. Los datos se suman, se restan,... y a veces se realizan operaciones más complejas. Operadores Aritméticos Son: Operador + Suma - Resta * Producto / División significado % Módulo (resto) Hay que tener en cuenta que el resultado de estos operadores varía notablemente si usamos enteros o si usamos números de coma flotante. Por ejemplo: double resultado1, d1=14, d2=5; int resultado2, i1=14, i2=5; resultado1= d1 / d2; resultado2= i1 / i2; resultado1 valdrá 2.8 mientras que resultado2 valdrá 2. Es más incluso: double resultado; int i1=7,i2=2; resultado=i1/i2; //Resultado valdrá 3 resultado=(double)i1/(double)i2; //Resultado valdrá

41 El operador del módulo (%) para calcular el resto de una división entera. Ejemplo: int resultado, i1=14, i2=5; resultado = i1 % i2; //El resultado será 4 Operadores Condicionales o relacionales Sirven para comparar valores. Siempre devuelven valores booleanos. Son: Operador < Menor > Mayor significado >= Mayor o igual <= Menor o igual == Igual!= Distinto Operadores Lógicos Los operadores lógicos (AND, OR y NOT), sirven para evaluar condiciones complejas. NOT sirve para negar una condición. Ejemplo: boolean mayordeedad, menordeedad; int edad = 21; mayordeedad = edad >= 18; //mayordeedad será true menordeedad =!mayordeedad; //menordeedad será false El operador && (AND) sirve para evaluar dos expresiones de modo que si ambas son ciertas, el resultado será true sino el resultado será false. Ejemplo: boolean carnetconducir=true; int edad=20; boolean puedeconducir= (edad>=18) && carnetconducir; //Si la edad es de al menos 18 años y carnetconducir es //true, puedeconducir es true 41

42 El operador (OR) sirve también para evaluar dos expresiones. El resultado será true si al menos uno de las expresiones es true. Ejemplo: boolean nieva =true, llueve=false, graniza=false; boolean maltiempo= nieva llueve graniza; Operadores de Asignación Permiten asignar valores a una variable. El fundamental es =. Pero sin embargo se pueden usar expresiones más complejas como: x += 3; En el ejemplo anterior lo que se hace es sumar 3 a la x (es lo mismo x+=3, que x=x+3). Eso se puede hacer también con todos estos operadores: += -= *= /= &= = ^= %= >>= <<= También se pueden concatenar asignaciones: x1 = x2 = x3 = 5; Otros operadores de asignación son ++ (incremento) y - - (decremento). Ejemplo: x++; //esto es x=x+1; x--; //esto es x=x-1; Pero hay dos formas de utilizar el incremento y el decremento. Se puede usar por ejemplo x++ o ++x La diferencia estriba en el modo en el que se comporta la asignación. 42

43 Ejemplo: int x=5, y=5, z; z=x++; //z vale 5, x vale 6 z=++y; //z vale 6, y vale 6 Operador (?) Este operador (conocido como if de una línea) permite ejecutar una instrucción u otra según el valor de la expresión. Sintaxis: expresionlogica?valorsiverdadero:valorsifalso; Ejemplo: paga=(edad>18)?6000:3000; En este caso si la variable edad es mayor de 18, la paga será de 6000, sino será de Se evalúa una condición y según es cierta o no se devuelve un valor u otro. Nótese que esta función ha de devolver un valor y no una expresión correcta. Es decir, no funcionaría: (edad>18)? paga=6000: paga=3000; /ERROR!!!! Conversión Entre Tipos (Casting) Hay veces en las que se deseará realizar algo como: int a;byte b=12; a=b; La duda está en si esto se puede realizar. La respuesta es que sí. Sí porque un dato byte es más pequeño que uno int y Java le convertirá de forma implícita. Sin embargo en: int a=1; byte b; b=a; El compilador devolverá error aunque el número 1 sea válido para un dato byte. Para ello hay que hacer un casting. Eso significa poner el tipo deseado entre paréntesis delante de la expresión. 43

44 int a=1; byte b; b= (byte) a; //No da error En el siguiente ejemplo: byte n1=100, n2=100, n3; n3= n1 * n2 /100; Aunque el resultado es 100, y ese resultado es válido para un tipo byte; lo que ocurrirá en realidad es que ocurrirá un error. Eso es debido a que primero multiplica 100 * 100 y como eso da 10000, no tiene más remedio el compilador que pasarlo a entero y así quedará aunque se vuelva a dividir. La solución correcta sería: n3 = (byte) (n1 * n2 / 100); Más ejemplos de CASTING int a = 24; byte b = (byte) a; short c = (short) a; long d = (long) a; Estructuras De Control De Flujo Las estructuras de control en Java son básicamente la misma que en C, con excepción del goto, que no existe. Por ejemplo: public final String tostring() { if (y<0) return x+"-i"+(-y); else return +x+"+i"+y; if Permite crear estructuras condicionales simples; en las que al cumplirse una condición se ejecuta una serie de instrucciones. Se puede hacer que otro 44

45 conjunto de instrucciones se ejecute si la condición es falsa. La condición es cualquier expresión que devuelva un resultado de true o false. Sintaxis: O bien: if (condición) instrucción si es true; else instrucción si es false; if (condición) { instrucciones que se ejecutan si la condición es true else { instrucciones que se ejecutan si la condición es false La parte else es opcional. Ejemplo: if ((diasemana>=1) && (diasemana<=5)){ trabajar = true; else { trabajar = false; Se pueden anidar varios if a la vez. De modo que se comprueban varios valores. Ejemplo: switch if (diasemana==1) dia= Lunes ; else if (diasemana==2) dia= Martes ; else if (diasemana==3) dia= Miércoles ; else if (diasemana==4) dia= Jueves ; else if (diasemana==5) dia= Viernes ; else if (diasemana==6) dia= Sábado ; else if (diasemana==7) dia= Domingo ; else dia=? ; 45

46 Permite ejecutar una serie de operaciones para el caso de que una variable tenga un valor entero dado. La ejecución saltea todos los case hasta que encuentra uno con el valor de la variable, y ejecuta desde allí hasta el final del case o hasta que encuentre un break, en cuyo caso salta al final del case. El default permite poner una serie de instrucciones que se ejecutan en caso de que la igualdad no se de para ninguno de los case. Sintaxis: switch (expresión) { case valor1: sentencias si la expresiona es igual al valor1; [break] case valor2: sentencias si la expresiona es igual al valor2; [break].. default: sentencias que se ejecutan si no se cumple ninguna de las anteriores Esta instrucción evalúa una expresión (que debe ser short, int, byte o char), y según el valor de la misma ejecuta instrucciones. Cada case contiene un valor de la expresión; si efectivamente la expresión equivale a ese valor, se ejecutan las instrucciones de ese case y de los siguientes. La instrucción break se utiliza para salir del switch. De tal modo que si queremos que para un determinado valor se ejecuten las instrucciones de un apartado case y sólo las de ese apartado, entonces habrá que finalizar ese case con un break. El bloque default sirve para ejecutar instrucciones para los casos en los que la expresión no se ajuste a ningún case. Ejemplo: 46

47 switch (diasemana) { case 1: dia= Lunes ; break; case 2: dia= Martes ; break; case 3: dia= Miércoles ; break; case 4: dia= Jueves ; break; case 5: dia= Viernes ; break; case 6: dia= Sábado ; break; case 7: dia= Domingo ; break; default: dia=? ; Ejemplo 2: switch (diasemana) { case 1: case 2: case 3: case 4: case 5: laborable=true; break; case 6: case 7: laborable=false; while 47

48 La instrucción while permite crear bucles. Un bucle es un conjunto de sentencias que se repiten si se cumple una determinada condición. Los bucles while agrupan instrucciones las cuales se ejecutan continuamente hasta que una condición que se evalúa sea falsa. La condición se mira antes de entrar dentro del while y cada vez que se termina de ejecutar las instrucciones del while Sintaxis: while (condición) { sentencias que se ejecutan si la condición es true Ejemplo (cálculo de factorial de un número, el factorial de 4 sería: 4*3*2*1): //factorial de 4 int n=4, factorial=1, temporal=n; while (temporal>0) { factorial*=temporal--; do while Crea un bucle muy similar al anterior, en la que también las instrucciones del bucle se ejecutan hasta que una condición pasa a ser falsa. La diferencia estriba en que en este tipo de bucle la condición se evalúa después de ejecutar las instrucciones; lo cual significa que al menos el bucle se ejecuta una vez. Sintaxis: do { instrucciones while (condición) for Es un bucle más complejo especialmente pensado para rellenar arrays o para ejecutar instrucciones controladas por un contador. Una vez más se ejecutan una serie de instrucciones en el caso de que se cumpla una determinada condición. Sintaxis: 48

49 for (expresióninicial; condición; expresiónencadavuelta) { instrucciones; La expresión inicial es una instrucción que se ejecuta una sola vez: al entrar por primera vez en el bucle for (normalmente esa expresión lo que hace es dar valor inicial al contador del bucle). La condición es cualquier expresión que devuelve un valor lógico. En el caso de que esa expresión sea verdadera se ejecutan las instrucciones. Cuando la condición pasa a ser falsa, el bucle deja de ejecutarse. La condición se valora cada vez que se terminan de ejecutar las instrucciones del bucle. Después de ejecutarse las instrucciones interiores del bucle, se realiza la expresión que tiene lugar tras ejecutarse las instrucciones del bucle (que, generalmente, incrementa o decrementa al contador). Luego se vuelve a evaluar la condición y así sucesivamente hasta que la condición sea falsa. Ejemplo (factorial): //factorial de 4 int n=4, factorial=1, temporal=n; for (temporal=n;temporal>0;temporal--){ factorial *=temporal; Sentencias De Salida De Un Bucle break Es una sentencia que permite salir del bucle en el que se encuentra inmediatamente. Hay que intentar evitar su uso ya que produce malos hábitos al programar. continue Instrucción que siempre va colocada dentro de un bucle y que hace que el flujo del programa ignore el resto de instrucciones del bucle; dicho de otra forma, va 49

50 hasta la siguiente iteración del bucle. Al igual que ocurría con break, hay que intentar evitar su uso. Ejemplo # import java.io.*; class Bucles { public static void main (String argv[ ]) { int i=0; La salida es: for (i=1; i<5; i++) { System.out.println("antes "+i); if (i==2) continue; if (i==3) break; System.out.println("después "+i); antes 1 después 1 antes 2 antes 3 i comienza en 1 (imprime "antes" y "después"); cuando pasa a 2, el continue salta al principio del bucle (no imprime el "después"). Finalmente, cuando "i" vale 3, el break da por terminado el bucle for. 50

51 PROGRAMACION ORIENTADA A OBJETOS CON JAVA Clase La primer característica de un programa Java es que este debe definir una Clase que lleve por nombre el mismo nombre del archivo fuente, en este caso si el nombre del archivo se llama Basico.java este debe incluir una definición de una Clase llamada Basico, nótese que ambos nombres coinciden en su sintaxis, esto es, ambos inician con letra mayúscula lo cual es una convención llevada acabo para la definición de Clases. Para definir una Clase se utiliza la palabra reservada class así como un calificador de acceso. Dentro de la definición de la Clase se deben incluir los respectivos métodos que podrán ser invocados. Ejemplo (Basico.java): public class Basico { public static void main(string args[]) { System.out.println("Un despliegue de Datos"); En el caso del ejemplo Basico.java únicamente se define el método main, dicho método es invocado por "default" al ejecutarse la Clase. Nótese que el método inicia con letra minúscula, esta es otra convención utilizada para diferenciarse de las distintas clases. La definición del método indica lo siguiente: o Primero se definen los modificadores del método en este caso son public y static. o También se define el valor de retorno del método: void, lo cual indica que no será retornado ningún valor. 51

52 o o Le sigue el nombre del método: main. Dentro de paréntesis se incluyen los parámetros de entrada para el método (String args[]). o Finalmente el Paquete.Clase.Método System.out.println envía un mensaje a la pantalla. Definir atributos de la clase (variables, propiedades o datos de las clases) Cuando se definen los datos de una determinada clase, se debe indicar el tipo de propiedad que es (String, int, double, int[][],...) y el modificador de acceso (public, private,...). El modificador indica en qué partes del código ese dato será visible. Ejemplo: class Persona { public String nombre; //Se puede acceder desde cualquier clase private int contraseña; //Sólo se puede acceder desde la clase Persona protected String dirección; //Acceden a esta propiedad esta clase y sus descendientes Por lo general las propiedades de una clase suelen ser privadas o protegidas, a no ser que se trate de un valor constante, en cuyo caso se declararán como públicos. Las variables locales de una clase pueden ser inicializadas. class auto{ public nruedas=4; Para poder acceder a los atributos de un objeto, se utiliza esta sintaxis: 52

53 objeto.atributo ejemplo: Miauto.velocidad; Creación De Constructores Un constructor es un método que es llamado automáticamente al crear un objeto de una clase, es decir al usar la instrucción new. Un constructor no es más que un método que tiene el mismo nombre que la clase. Con lo cual para crear un constructor basta definir un método en el código de la clase que tenga el mismo nombre que la clase. Ejemplo: class Ficha { private int casilla; Ficha() { //constructor casilla = 1; public void avanzar(int n) { casilla += n; public int casillaactual(){ return casilla; public class app { public static void main(string[] args) { Ficha ficha1 = new Ficha(); ficha1.avanzar(3); System.out.println(ficha1.casillaActual());//Da 4 53

54 En la línea Ficha ficha1 = new Ficha(); es cuando se llama al constructor, que es el que coloca inicialmente la casilla a 1. Pero el constructor puede tener parámetros: class Ficha { private int casilla; //Valor inicial de la propiedad Ficha(int n) { //constructor casilla = n; public void avanzar(int n) { casilla += n; public int casillaactual(){ return casilla; public class app { public static void main(string[] args) { Ficha ficha1 = new Ficha(6); ficha1.avanzar(3); System.out.println(ficha1.casillaActual());//Da 9 En este otro ejemplo, al crear el objeto ficha1, se le da un valor a la casilla, por lo que la casilla vale al principio 6. Hay que tener en cuenta que puede haber más de un constructor para la misma clase. Al igual que ocurre con los métodos, los constructores se pueden sobrecargar. De este modo en el código anterior de la clase Ficha se podrían haber colocado los dos constructores que hemos visto, y sería entonces posible este código: Ficha ficha1= new Ficha(); //La propiedad casilla de la //ficha valdrá 1 54

55 Ficha ficha1= new Ficha(6); //La propiedad casilla de la //ficha valdrá 6 Cuando se sobrecargan los constructores (se utilizan varias posibilidades de constructor), se pueden hacer llamadas a constructores mediante el objeto this Métodos Los métodos se utilizan de la misma forma que los atributos, excepto porque los métodos poseen siempre paréntesis, dentro de los cuales pueden ir valores necesarios para la ejecución del método (parámetros): objeto.método(argumentosdelmétodo) Los métodos siempre tienen paréntesis (es la diferencia con las propiedades) y dentro de los paréntesis se colocan los argumentos del método. Que son los datos que necesita el método para funcionar. Por ejemplo: Miauto.avanza(5); Lo cual podría hacer que el auto avance a 5 Km/h. Definir Métodos De Clase (Operaciones O Funciones De Clase) Un método es una llamada a una operación de un determinado objeto. Al realizar esta llamada (también se le llama enviar un mensaje), el control del programa pasa a ese método y lo mantendrá hasta que el método finalice o se haga uso de return. Para que un método pueda trabajar, normalmente hay que pasarle unos datos en forma de argumentos o parámetros, cada uno de los cuales se separa por comas. Ejemplos: balón.botar(); //sin argumentos micoche.acelerar(10); ficha.comer(posición15); //posición 15 es una variable que se pasa como argumento 55

56 partida.empezarpartida( 18:15,colores); Los métodos de la clase se definen dentro de ésta. Hay que indicar un modificador de acceso (public, private, protected o ninguno, al igual que ocurre con las variables y con la propia clase) y un tipo de datos, que indica qué tipo de valores devuelve el método. Esto último se debe a que los métodos son funciones que pueden devolver un determinado valor (un entero, un texto, un valor lógico,...) mediante el comando return. Si el método no devuelve ningún valor, entonces se utiliza el tipo void que significa que no devuelve valores (en ese caso el método no tendrá instrucción return). El último detalle a tener en cuenta es que los métodos casi siempre necesitan datos para realizar la operación, estos datos van entre paréntesis y se les llama argumentos. Al definir el método hay que indicar que argumentos se necesitan y de qué tipo son. Ejemplo: public class vehiculo { /** Función principal */ int ruedas; private double velocidad=0; String nombre; /** Aumenta la velocidad*/ public void acelerar(double cantidad) { velocidad += cantidad; /** Disminuye la velocidad*/ public void frenar(double cantidad) { velocidad -= cantidad; /** Devuelve la velocidad*/ 56

57 public double obtenervelocidad(){ return velocidad; public static void main(string args[]){ vehiculo micoche = new vehiculo(); micoche.acelerar(12); // Da 7.0 micoche.frenar(5); System.out.println(miCoche.obtenerVelocidad()); Argumentos por valor y por referencia En todos los lenguajes éste es un tema muy importante. Los argumentos son los datos que recibe un método y que necesita para funcionar. Ejemplo: public class Matemáticas { public double factorial(int n){ double resultado; for (resultado=n;n>1;n--) resultado*=n; return resultado; public static void main(string args[]){ Matemáticas m1=new Matemáticas(); double x=m1.factorial(25);//llamada al método En el ejemplo anterior, el valor 25 es un argumento requerido por el método factorial para que éste devuelva el resultado (que será el factorial de 25). En el código del método factorial, este valor 25 es copiado a la variable n, que es la encargada de almacenar y utilizar este valor. 57

58 Se dice que los argumentos son por valor, si la función recibe una copia de esos datos, es decir la variable que se pasa como argumento no estará afectada por el código. Ejemplo: class prueba { public void metodo1(int entero){ entero=18; public static void main(string args[]){ int x=24; prueba miprueba = new prueba(); miprueba.metodo1(x); System.out.println(x); //Escribe 24, no 18 Este es un ejemplo de paso de parámetros por valor. La variable x se pasa como argumento o parámetro para el método metodo1, allí la variable entero recibe una copia del valor de x en la variable entero, y a esa copia se le asigna el valor 18. Sin embargo la variable x no está afectada por esta asignación. Sin embargo en este otro caso: class prueba { public void metodo1(int[] entero){ entero[0]=18; public static void main(string args[]){ int x[]={24,24; prueba miprueba = new prueba(); miprueba.metodo1(x); System.out.println(x[0]); //Escribe 18, no 24 Aquí sí que la variable x está afectada por la asignación entero[0]=18. La razón es porque en este caso el método no recibe el valor de esta variable, 58

59 sino la referencia, es decir la dirección física de esta variable. Entero no es una replica de x, es la propia x llamada de otra forma. Los tipos básicos (int, double, char, boolean, float, short y byte) se pasan por valor. También se pasan por valor las variables String. Los objetos y arrays se pasan por referencia. Devolución de valores Los métodos pueden devolver valores básicos (int, short, double, etc.), Strings, arrays e incluso objetos. En todos los casos es el comando return el que realiza esta labor. En el caso de arrays y objetos, devuelve una referencia a ese array u objeto. Ejemplo: class FabricaArrays { public int[] obtenarray(){ int array[]= {1,2,3,4,5; return array; public class returnarray { public static void main(string[] args) { FabricaArrays fab=new FabricaArrays(); int nuevoarray[]=fab.obtenarray(); Sobrecarga De Métodos Una propiedad de la POO es el polimorfismo. Java posee esa propiedad ya que admite sobrecargar los métodos. Esto significa crear distintas variantes del mismo método. Ejemplo: class Matemáticas{ 59

60 public double suma(double x, double y) { return x+y; public double suma(double x, double y, double z){ return x+y+z; public double suma(double[] array){ double total =0; for(int i=0; i<array.length;i++){ total+=array[i]; return total; La clase matemáticas posee tres versiones del método suma. una versión que suma dos números double, otra que suma tres y la última que suma todos los miembros de un array de doubles. Desde el código se puede utilizar cualquiera de las tres versiones según convenga. Método principal main El método principal main de una Clase Java es inalterable, en este sentido inalterable se refiere a sus características: o o o Siempre debe incluir los calificadores: public y static. Nunca puede retornar un valor como resultado, es decir siempre debe indicar el tipo de dato void como retorno. Su parámetro de entrada siempre será un arreglo de String (String[]) el cual es tomado de la línea de comandos o una fuente alterna. Aunque no es un obligacion definir el método main dentro de toda Clase Java, dicho método representa el único mecanismo automático para realizar tareas al invocarse una Clase, esto es, al momento de ejecutarse determinada Clase siempre será ejecutado todo el contenido dentro de dicho método. 60

61 Para generar una Clase compilada (Byte-Code) se utiliza el comando javac : javac Basico.java Lo anterior genera un archivo llamado Basico.class; para ejecutar este Byte-Code es empleado el comando java: java Basico Al invocar el comando anterior será ejecutada la Clase Basico.class. Nótese que el comando java recibe el nombre de la Clase sin la extensión.class. Nota: Si se utiliza un IDE de desarrollo este trae opciones para compilar y ejecutar la clase y mostrara los resultados en su propia interfase en algún panel de salida. La Referencia This La palabra this es una referencia al propio objeto en el que estamos. Ejemplo: class punto { int posx, posy;//posición del punto punto(posx, posy){ this.posx=posx; this.posy=posy; En el ejemplo hace falta la referencia this para clarificar cuando se usan las propiedades posx y posy, y cuando los argumentos con el mismo nombre. Ejemplo: class punto { int posx, posy; /**Suma las coordenadas de otro punto*/ public void suma(punto punto2){ posx = punto2.posx; 61

62 posy = punto2.posy; /** Dobla el valor de las coordenadas del punto*/ public void dobla(){ suma(this); En el ejemplo anterior, la función dobla, dobla el valor de las coordenadas pasando el propio punto como referencia para la función suma (un punto sumado a sí mismo, daría el doble). Los posibles usos de this son: o o o o this. Referencia al objeto actual. Se usa por ejemplo pasarle como parámetro a un método cuando es llamado desde la propia clase. this.atributo. Para acceder a una propiedad del objeto actual. this.método(parámetros). Permite llamar a un método del objeto actual con los parámetros indicados. this(parámetros). Permite llamar a un constructor del objeto actual. Esta llamada sólo puede ser empleada en la primera línea de un constructor. Manejo de Objetos Se les llama instancias de clase. Son un elemento en sí de la clase, Un objeto se crea utilizando el llamado constructor de la clase. El constructor es el método que permite iniciar el objeto. Creación De Objetos De La Clase Una vez definida la clase, se pueden utilizar objetos de la clase. Normalmente consta de dos pasos. Su declaración, y su creación. La declaración consiste en indicar que se va a utilizar un objeto de una clase determinada. Y se hace igual que cuando se declara una variable simple. Ejemplo: 62

63 Auto Miauto; Eso declara el objeto Miauto como objeto de tipo Auto; se supone que previamente se ha definido la clase Auto. Para poder utilizar un objeto, hay que crearle de verdad. Eso consiste en utilizar el operador new. Ejemplo: noriadepalencia = new Noria(); Al hacer esta operación el objeto reserva la memoria que necesita y se inicializa el objeto mediante su constructor. Organización de las Clases Paquetes (Packages) son un grupo o librería de clases desarrolladas en java que se utilizan para algo específico. Las principales clases de java son las siguientes (incluidas en el JDK): o o o o o java.applet: Creado para soportar la creación de applet Java, el paquete java.applet permite a las aplicaciones ser descargadas sobre una red y ejecutarse dentro de una sandbox.. java.awt: La Abstract Window Toolkit contiene rutinas para soportar operaciones básicas GUI y utiliza ventanas básicas desde el sistema nativo subyacente. java.awt.event: Soporte y procesamiento de eventos para controles awt. java.io: El paquete java.io contiene clases que soportan entrada/salida. Las clases del paquete son principalmente streams; sin embargo, se incluye una clase para ficheros de acceso aleatorio. java.lang: El paquete Java java.lang contiene clases fundamentales e interfaces fuertemente relacionadas con el lenguaje y el sistema runtime. Esto incluye las clases raíz que forman la jerarquía de clases, tipos relacionados con la definición del lenguaje, excepciones básicas, 63

64 o o o o o funciones matemáticas, Hilos, funciones de seguridad, así como también alguna información sobre el sistema nativo subyacente. java.net: El paquete java.net suminista rutinas especiales IO para redes, permitiendo las peticiones HTTP, así como también otras transacciones comunes. java.util: Las estructuras de datos que agregan objetos son el foco del paquete java.util. En el paquete está incluida la API Collections, una jerarquía organizada de estructura de datos influenciada fuertemente por consideraciones de patrones de diseño. javax.swing: Swing es una colección de rutinas que se construyen sobre java.awt para suministrar un toolkit de widgets independiente de plataforma. javax.swing.event: Soporte y procesamiento de eventos para controles swing. java.math: El paquete java.math soporta aritmética multiprecision (incluyendo operaciones aritméticas modulares) y suministra generadores de números primos multiprecision usados para la generación de claves criptográficas. Paquetes Un paquete es una colección de clases e interfaces relacionadas. El compilador de Java usa los paquetes para organizar la compilación y ejecución. Es decir, un paquete es una biblioteca. De hecho el nombre completo de una clase es el nombre del paquete en el que está la clase, punto y luego el nombre de la clase. Es decir si la clase Coche está dentro del paquete locomoción, el nombre completo de Coche es locomoción.coche. A veces resulta que un paquete está dentro de otro paquete, entonces habrá que indicar la ruta completa a la clase. Por ejemplo locomoción.motor.motor1300 Mediante el comando import, se evita tener que colocar el nombre completo. El comando import se coloca antes de definir la clase. Ejemplo: 64

65 import locomoción.motor.motor1300; Gracias a esta instrucción para utilizar la clase Motor1300 no hace falta indicar el paquete en el que se encuentra, basta indicar sólo Motor1300. Ejemplo: import locomoción.*; //Importa todas las clases del paquete locomoción Esta instrucción no importa el contenido de los paquetes interiores a locomoción (es decir que si la clase Coche está dentro del paquete motor, no sería importada con esa instrucción, ya que el paquete motor no ha sido importado, sí lo sería la clase locomoción.barcodevela). Por ello en el ejemplo lo completo sería: import locomoción.*; import locomoción.motor.*; Cuando desde un programa se hace referencia a una determinada clase se busca ésta en el paquete en el que está colocada la clase y, sino se encuentra, en los paquetes que se han importado al programa. Si ese nombre de clase se ha definido en un solo paquete, se usa. Si no es así podría haber ambigüedad por ello se debe usar un prefijo delante de la clase con el nombre del paquete. Es decir: paquete.clase O incluso: paquete1.paquete clase En el caso de que el paquete sea subpaquete de otro más grande. Las clases son visibles en el mismo paquete a no ser que se las haya declarado con el modificador private. Organización de los paquetes Los paquetes en realidad son subdirectorios cuya raíz debe ser absolutamente accesible por el sistema operativo. Para ello es necesario usar la variable de entorno CLASSPATH de la línea de comandos. Esta variable se suele definir en el archivo autoexec.bat o en 65

66 MI PC en el caso de las últimas versiones de Windows. Hay que añadirla las rutas a las carpetas que contienen los paquetes (normalmente todos los paquetes se suelen crear en la misma carpeta), a estas carpetas se las llama filesystems. Así para el paquete prueba.reloj tiene que haber una carpeta prueba, dentro de la cual habrá una carpeta reloj y esa carpeta prueba tiene que formar parte del classpath. Una clase se declara perteneciente aun determinado paquete usando la instrucción package al principio del código (sin usar esta instrucción, la clase no se puede compilar). Si se usa package tiene que ser la primera instrucción del programa Java: //Clase perteneciente al paquete tema5 que está en ejemplos package ejemplos.tema5; En los entornos de desarrollo o IDEs puede (NetBeans, JBuilder,...) se uno despreocupar de la variable classpath ya que poseen mecanismos de ayuda para gestionar los paquetes. Pero hay que tener en cuenta que si se compila a mano mediante el comando java (véase proceso de compilación, página i) se debe añadir el modificador -cp para que sean accesibles las clases contenidas en paquetes del classpath (por ejemplo java -cp prueba.java). El uso de los paquetes permite que al compilar sólo se compile el código de la clase y de las clases importadas, en lugar de compilar todas las librerías. Sólo se compila lo que se utiliza. Diagrama de Paquetes 66

67 Uso de los métodos print y println println( mensaje ) Escribe el mensaje y luego se produce un cambio de línea que equivale a pulsar [Return] print( mensaje ) Escribe el mensaje y el cursor se sitúa al final del mensaje y en la misma línea. Para recordarlo piensa en la siguiente fórmula : Esto seria una equivalencia más explicativa: println = print + ln (línea nueva) El comando \n dentro del mensaje del método print o println también realiza un salto de línea en el mensaje. Ejercicio 4 class J001 { public static void main(string [] args) { System.out.println("Hola\nQue tal"); System.out.println("Uno\nDos\nTres\nCuatro"); Ejercicio 5 class J002 { 67

68 Instrucción Import public static void main(string [] args) { System.out.println("Hola"); System.out.println("Adios"); System.out.println(""); System.out.print("Pues vale"); System.out.print("Eso"); System.out.print("Vale"); Hay código que se puede utilizar en los programas que realicemos en Java. Se importa clases de objetos que están contenidas, a su vez, en paquetes estándares. Por ejemplo la clase Date es una de las más utilizadas, sirve para manipular fechas. Si alguien quisiera utilizar en su código objetos de esta clase, necesita incluir una instrucción que permita utilizar esta clase. La sintaxis de esta instrucción es: import paquete.subpaquete.subsubapquete...clase Esta instrucción se coloca en la parte superior del código. Para la clase Date sería: import java.util.date Lo que significa, importar en el código la clase Date que se encuentra dentro del paquete util que, a su vez, está dentro del gran paquete llamado java. También se puede utilizar el asterisco en esta forma: import java.util.* Esto significa que se va a incluir en el código todas las clases que están dentro del paquete util de java. Ejemplo: 68

69 // J003.java = dibuja 2 circunferencias import java.awt.*; import java.awt.event.*; class J003 extends Frame { public J003() { settitle("dos circunferencias"); public static void main(string [] args) { Frame f=new J003(); f.addwindowlistener(new WindowAdapter() { public void windowclosing(windowevent e) { System.exit(0); ); f.setsize(300,200); f.setvisible(true); public void paint(graphics g){ g.setcolor(color.red); g.drawoval(10,30,30,30); g.setcolor(color.blue); g.drawoval(35,30,30,30); g.drawstring("dos circunferencias",40,100); f.setsize(600,400) Determina el tamaño de la ventana: 1ª coordenada = 600 = anchura en píxels, 2ª coordenada = 400 = altura en píxels. g.setcolor(color,red) Establece el rojo como color de dibujo. 69

70 g.drawoval(10,30,30,30) Dibuja una circunferencia cuyo vértice superior izquierdo se encuentra en el punto 10,30. La tercera coordenada es el diametro horizontal y la cuarta el diámetro vertical. Como los dos diámetros son iguales, resulta una circunferencia. Si fueran distintos, seria una elipse. g.drawstring( Dos circunferencias,40,100) Dibuja el texto que hay entre comillas en el punto de coordenadas 40,100 (1ª coordenada= distáncia horizontal desde el borde izquierdo, 2ª coordenada = distáncia vertical desde el borde superior). Interfaces La limitación de que sólo se puede heredar de una clase, hace que haya problemas ya que muchas veces se deseará heredar de varias clases. Aunque ésta no es la finalidad directa de las interfaces, sí que tiene cierta relación. Mediante interfaces se definen una serie de comportamientos de objeto. Estos comportamientos puede ser implementados en una determinada clase. No definen el tipo de objeto que es, sino lo que puede hacer (sus capacidades). Por ello lo normal es que el nombre de las interfaces terminen con el texto able (configurable, modificable, cargable, etc). Por ejemplo en el caso de la clase Coche, esta deriva de la superclase Vehículo, pero además puesto que es un vehículo a motor, puede implementar métodos de una interfaz llamada por ejemplo arrancable. Se dirá entonces que la clase Coche es arrancable. Utilizar interfaces Para hacer que una clase utilice una interfaz, se añade detrás del nombre de la clase la palabra implements seguida del nombre del interfaz. Se pueden poner varios nombres de interfaces separados por comas (solucionando, en cierto modo, el problema de la herencia múltiple). class Coche extends vehiculo implements arrancable { public void arrancar (){ 70

71 public void detenermotor(){ Hay que tener en cuenta que la interfaz arrancable no tiene porque tener ninguna relación de herencia con la clase vehículo, es más se podría implementar el interfaz arrancable a una bomba de agua. Creación de interfaces Una interfaz en realidad es una serie de constantes y métodos abstractos. Cuando una clase implementa un determinado interfaz debe anular los métodos abstractos de éste, redefiniéndolos en la propia clase. Esta es la base de una interfaz, en realidad no hay una relación sino que hay una obligación por parte de la clase que implemente la interfaz de redefinir los métodos de ésta. Una interfaz se crea exactamente igual que una clase (se crean en archivos propios también), la diferencia es que la palabra interface sustituye a la palabra class y que sólo se pueden definir en un interfaz constantes y métodos abstractos. Todas las interfaces son abstractas y sus métodos también son todos abstractos y públicos (no hace falta poner el modificar abstract se toma de manera implícita). Las variables se tienen obligatoriamente que inicializar. Ejemplo: interface arrancable(){ boolean motorarrancado=false; void arrancar(); void detenermotor(); Los métodos son simples prototipos y toda variable se considera una constante (a no ser que se redefina en una clase que implemente esta interfaz, lo cual no tendría mucho sentido). 71

72 Subinterfaces Una interfaz puede heredarse de otra interfaz, como por ejemplo en: interface dibujable extends escribible, pintable { Dibujable es subinterfaz de escribible y pintable. Es curioso, pero los interfaces sí admiten herencia múltiple. Esto significa que la clase que implemente el interfaz dibujable deberá incorporar los métodos definidos en escribible y pintable. Variables de interfaz Al definir una interfaz, se pueden crear después variables de interfaz. Se puede interpretar esto como si el interfaz fuera un tipo especial de datos (que no de clase). La ventaja que proporciona es que pueden asignarse variables interfaz a cualquier objeto de una clase que implementa la interfaz. Esto permite cosas como: Arrancable motorcito; //motorcito es una variable de tipo arrancable Coche c=new Coche(); //Objeto de tipo coche BombaAgua ba=new BombaAgua(); //Objeto de tipo BombaAgua motorcito=c; //Motorcito apunta a c motorcito.arrancar() //Se arrancará c motorcito=ba; //Motorcito apunta a ba motorcito=arrancar; //Se arranca la bomba de agua El juego que dan estas variables es impresionante, debido a que fuerzan acciones sobre objetos de todo tipo, y sin importar este tipo; siempre 72

73 y cuando estos objetos pertenezcan a clases que implementen el interfaz. Interfaces como funciones de retroinvocación En C++ una función de retroinvocación es un puntero que señala a un método o a un objeto. Se usan para controlar eventos. En Java se usan interfaces para este fin. Ejemplo: interface Escribible { void escribe(string texto); class Texto implements Escribible { public void escribe(texto){ System.out.println(texto); class Prueba { Escribible escritor; public Prueba(Escribible e){ escritor=e; public void enviatexto(string s){ escritor.escribe(s); En el ejemplo escritor es una variable de la interfaz Escribible, cuando se llama a su método escribe, entonces se usa la implementación de la clase texto. Herencia Es una de las armas fundamentales de la programación orientada a objetos. Permite crear nuevas clases que heredan características presentas en clases anteriores. Esto facilita enormemente el trabajo porque ha permitido crear clases 73

74 estándar para todos los programadores y a partir de ellas crear nuestras propias clases personales. Esto es más cómodo que tener que crear nuestras clases desde cero. Para que una clase herede las características de otra hay que utilizar la palabra clave extends tras el nombre de la clase. A esta palabra le sigue el nombre de la clase cuyas características se heredarán. Sólo se puede tener herencia de una clase (a la clase de la que se hereda se la llama superclase y a la clase heredada se la llama subclase). Ejemplo: class coche extends vehiculo { //La clase coche parte de la definición de vehículo Métodos y propiedades no heredados Por defecto se heredan todos los métodos y propiedades protected y public (no se heredan los private). Además si se define un método o propiedad en la subclase con el mismo nombre que en la superclase, entonces se dice que se está redefiniendo el método, con lo cual no se hereda éste, sino que se reemplaza por el nuevo. Ejemplo: class vehiculo { public int velocidad; public int ruedas; 74

75 public void parar() { velocidad = 0; public void acelerar(int kmh) { velocidad += kmh; class coche extends vehiculo{ public int ruedas=4; public int gasolina; public void repostar(int litros) { gasolina+=litros; public class app { public static void main(string[] args) { coche coche1=new coche(); coche.acelerar(80);//método heredado coche.repostar(12); Anulación De Métodos Como se ha visto, las subclases heredan los métodos de las superclases. Pero es más, también los pueden sobrecargar para proporcionar una versión de un determinado método. Por último, si una subclase define un método con el mismo nombre, tipo y argumentos que un método de la superclase, se dice entonces que se sobrescribe o anula el método de la superclase. Ejemplo: 75

76 Super A veces se requiere llamar a un método de la superclase. Eso se realiza con la palabra reservada super. Si this hace referencia a la clase actual, super hace referencia a la superclase respecto a la clase actual, con lo que es un método imprescindible para poder acceder a métodos anulados por herencia. Ejemplo public class vehiculo{ double velocidad; public void acelerar(double cantidad){ velocidad+=cantidad; public class coche extends vehiculo{ double gasolina; public void acelerar(double cantidad){ super.acelerar(cantidad); gasolina*=0.9; 76

77 En el ejemplo anterior, la llamada super.acelerar(cantidad) llama al método acelerar de la clase vehículo (el cual acelerará la marcha). Es necesario redefinir el método acelerar en la clase coche ya que aunque la velocidad varía igual que en la superclase, hay que tener en cuenta el consumo de gasolina. Se puede incluso llamar a un constructor de una superclase, usando la sentencia super(). Ejemplo: public class vehiculo{ double velocidad; public vehiculo(double v){ velocidad=v; public class coche extends vehiculo{ double gasolina; public coche(double v, double g){ super(v); //Llama al constructor de la clase vehiculo gasolina=g Por defecto Java realiza estas acciones: o o o Si la primera instrucción de un constructor de una subclase es una sentencia que no es ni super ni this, Java añade de forma invisible e implícita una llamada super() al constructor por defecto de la superclase, luego inicia las variables de la subclase y luego sigue con la ejecución normal. Si se usa super(..) en la primera instrucción, entonces se llama al constructor seleccionado de la superclase, luego inicia las propiedades de la subclase y luego sigue con el resto de sentencias del constructor. Finalmente, si esa primera instrucción es this(..), entonces se llama al constructor seleccionado por medio de this, y después continúa con las 77

78 sentencias del constructor. La inicialización de variables la habrá realizado el constructor al que se llamó mediante this. 78

79 EXCEPCIONES Introducción a las excepciones Uno de los problemas más importantes al escribir aplicaciones es el tratamiento de los errores. Errores no previstos que distorsionan la ejecución del programa. Las excepciones de Java hacen referencia e este hecho. Se denomina excepción a una situación que no se puede resolver y que provoca la detención del programa; es decir una condición de error en tiempo de ejecución (es decir cuando el programa ya ha sido compilado y se está ejecutando). Ejemplos: El archivo que queremos abrir no existe Falla la conexión a una red La clase que se desea utilizar no se encuentra en ninguno de los paquetes reseñados con import Los errores de sintaxis son detectados durante la compilación. Pero las excepciones pueden provocar situaciones irreversibles, su control debe hacerse en tiempo de ejecución y eso presenta un gran problema. En Java se puede preparar el código susceptible a provocar errores de ejecución de modo que si ocurre una excepción, el código es lanzado (throw) a una determinada rutina previamente preparada por el programador, que permite manipular esa excepción. Si la excepción no fuera capturada, la ejecución del programa se detendría irremediablemente. En Java hay muchos tipos de excepciones (de operaciones de entrada y salida, de operaciones irreales. El paquete java.lang.exception y sus subpaquetes contienen todos los tipos de excepciones. Cuando se produce un error se genera un objeto asociado a esa excepción. Este objeto es de la clase Exception o de alguna de sus herederas. Este objeto se pasa al código que se ha definido para manejar la excepción. Dicho código puede manipular las propiedades del objeto Exception. 79

80 Hay una clase, la java.lang.error y sus subclases que sirven para definir los errores irrecuperables más serios. Esos errores causan parada en el programa, por lo que el programador no hace falta que los manipule. Estos errores les produce el sistema y son incontrolables para el programador. Las excepciones son fallos más leves, y más manipulables. La estructura Try match. Las sentencias que tratan las excepciones son try y catch. La sintaxis es: try { instrucciones que se ejecutan salvo que haya un error catch (ClaseExcepción objetoquecapturalaexcepción) { instrucciones que se ejecutan si hay un error Puede haber más de una sentencia catch para un mismo bloque try. Ejemplo: try { readfromfile( arch ); catch(filenotfoundexception e) { //archivo no encontrado catch (IOException e) { Jerarquía de Excepciones 80

81 Dentro del bloque try se colocan las instrucciones susceptibles de provocar una excepción, el bloque catch sirve para capturar esa excepción y evitar el fin de la ejecución del programa. Desde el bloque catch se maneja, en definitiva, la excepción. Cada catch maneja un tipo de excepción. Cuando se produce una excepción, se busca el catch que posea el manejador de excepción adecuado, será el que utilice el mismo tipo de excepción que se ha producido. Esto puede causar problemas si no se tiene cuidado, ya que la clase Exception es la superclase de todas las demás. Por lo que si se produjo, por ejemplo, una excepción de tipo AritmethicException y el primer catch captura el tipo genérico Exception, será ese catch el que se ejecute y no los demás. Por eso el último catch debe ser el que capture excepciones genéricas y los primeros deben ser los más específicos. Lógicamente si vamos a tratar a todas las excepciones (sean del tipo que sean) igual, entonces basta con un solo catch que capture objetos Exception. Manejo de excepciones 81

82 Siempre se debe controlar una excepción, de otra forma nuestro software está a merced de los fallos. En la programación siempre ha habido dos formas de manejar la excepción: Interrupción. En este caso se asume que el programa ha encontrado un error irrecuperable. La operación que dio lugar a la excepción se anula y se entiende que no hay manera de regresar al código que provocó la excepción. Es decir, la operación que dio pies al error, se anula. Reanudación. Se puede manejar el error y regresar de nuevo al código que provocó el error. La filosofía de Java es del tipo interrupción, pero se puede intentar emular la reanudación encerrando el bloque try en un while que se repetirá hasta que el error deje de existir. Ejemplo: boolean indicenovalido=true; int i; //Entero que tomará números aleatorios de 0 a 9 String texto[]={ Uno, Dos, Tres, Cuatro, Cinco ; while(indicenovalido){ try{ i=math.round(math.random()*9); System.out.println(texto[i]; indicenovalido=false; catch(arrayindexoutofboundsexception exc){ System.out.println( Fallo en el índice ); En el código anterior, el índice i calcula un número del 0 al 9 y con ese número el código accede al array texto que sólo contiene 5 elementos. Esto producirá muy a menudo una excepción del tipo ArrayIndexOutOfBoundsException que es manejada por el catch correspondiente. Normalmente no se continuaría 82

83 intentando. Pero como tras el bloque catch está dentro del while, se hará otro intento y así hasta que no haya excepción, lo que provocará que indicenovalido valga true y la salida, al fin, del while. Como se observa en la Error! No se encuentra el origen de la referencia., la clase Exception es la superclase de todos los tipos de excepciones. Esto permite utilizar una serie de métodos comunes a todas las clases de excepciones: String getmessage(). Obtiene el mensaje descriptivo de la excepción o una indicación específica del error ocurrido: try{ catch (IOException ioe){ System.out.println(ioe.getMessage()); String tostring(). Escribe una cadena sobre la situación de la excepción. Suele indicar la clase de excepción y el texto de getmessage(). void printstacktrace(). Escribe el método y mensaje de la excepción (la llamada información de pila). El resultado es el mismo mensaje que muestra el ejecutor (la máquina virtual de Java) cuando no se controla la excepción. Uso del throws Al llamar a métodos, ocurre un problema con las excepciones. El problema es, si el método da lugar a una excepción, quién la maneja? El propio método? O el código que hizo la llamada al método? Con lo visto hasta ahora, sería el propio método quien se encargara de sus excepciones, pero esto complica el código. Por eso otra posibilidad es hacer que la excepción la maneje el código que hizo la llamada. 83

84 Esto se hace añadiendo la palabra throws tras la primera línea de un método. Tras esa palabra se indica qué excepciones puede provocar el código del método. Si ocurre una excepción en el método, el código abandona ese método y regresa al código desde el que se llamó al método. Allí se posará en el catch apropiado para esa excepción. Ejemplo: void usararchivo (String archivo) throws IOException, InterruptedException {... En este caso se está indicando que el método usararchivo puede provocar excepciones del tipo IOException y InterruptedException. Esto significará, además, que el que utilice este método debe preparar el catch correspondiente para manejar los posibles errores. Ejemplo: try{ objeto.usararchivo( C:\texto.txt );//puede haber excepción catch(ioexception ioe){.. catch(interruptedexception ie){......//otros catch para otras posibles excepciones Uso del throw Esta instrucción nos permite lanzar a nosotros nuestras propias excepciones (o lo que es lo mismo, crear artificialmente nosotros las excepciones). Ante: throw new Exception(); 84

85 El flujo del programa se dirigirá a la instrucción try/catch más cercana. Se pueden utilizar constructores en esta llamada (el formato de los constructores depende de la clase que se utilice): throw new Exception( Error grave, grave ); Eso construye una excepción con el mensaje indicado. throw permite también relanzar excepciones. Esto significa que dentro de un catch podemos colocar una instrucción throw para lanzar la nueva excepción que será capturada por el catch correspondiente: try{ catch(arrayindexoutofboundsexception exc){ throw new IOException(); catch(ioexception){ El segundo catch capturará también las excepciones del primer tipo Uso del finally La cláusula finally está pensada para limpiar el código en caso de excepción. Su uso es: try{ catch (FileNotFoundException fnfe){ catch(ioexception ioe){ catch(exception e){ finally{...//instrucciones de limpieza 85

86 Las sentencias finally se ejecutan tras haberse ejecutado el catch correspondiente. Si ningún catch capturó la excepción, entonces se ejecutarán esas sentencias antes de devolver el control al siguiente nivel o antes de romperse la ejecución. Hay que tener muy en cuenta que las sentencias finally se ejecutan independientemente de si hubo o no excepción. Es decir esas sentencias se ejecutan siempre, haya o no excepción. Son sentencias a ejecutarse en todo momento. Por ello se coloca en el bloque finally código común para todas las excepciones (y también para cuando no hay excepciones). Clases Envoltorio (wrapper) No son más que clases que modelan los tipos de datos primitivos tales como enteros y flotantes, precisamente estos tipos primitivos son los únicos elementos en Java que no son clases. Cabe destacar una diferencia notable entre los tipos primitivos y sus wrapper: Los tipos primitivos se pasan como argumento a los métodos por valor, mientras que los objetos se pasan por referencia. Esto implica una ventaja en cuanto a eficiencia. Por otra parte estos wrapper ofrecen métodos de conversión muy convenientes. Estas clases se encuentran en java.lang, derivan de Number que deriva de Object. Cada una de estas clases contiene un valor primitivo del tipo relacionado, por ejemplo un objeto Integer contiene un int como atributo. En Java se dice que todo es considerado un objeto. Para hacer que esta filosofía sea más real se han diseñado una serie de clases relacionadas con los tipos básicos. El nombre de estas clases es: Clase java.lang.void java.lang.boolean java.lang.character java.lang.byte java.lang.short java.lang.integer Representa al tipo básico.. void boolean char byte short int 86

87 java.lang.long java.lang.float java.lang.double long float double Hay que tener en cuenta que no son equivalentes a los tipos básicos. La creación de estos tipos lógicamente requiere usar constructores, ya que son objetos y no tipos básicos. Double n=new Double(18.3); Double o=new Double( 18.5 ); El constructor admite valores del tipo básico relacionado e incluso valores String que contengan texto convertible a ese tipo básico. Si ese texto no es convertible, ocurre una excepción del tipo NumberFormatException. La conversión de un String a un tipo básico es una de las utilidades básicas de estas clases, por ello estas clases poseen el método estático valueof entre otros para convertir un String en uno de esos tipos. Ejemplos: String s= 2500 ; Integer a=integer.valueof(s); Short b=short.valueof(s); Double c=short.valueof(s); Byte d=byte.valueof(s);//excepción!!! Hay otro método en cada una de esas clases que se llama parse. La diferencia estriba en que en los métodos parse la conversión se realiza hacia tipos básicos (int, double, float, boolean,...) y no hacia las clase anteriores. Ejemplo: String s= 2500 ; int y=integer.parseint(s); short z=short.parseshort(s); double c=short.parsedouble(s); byte x=byte.parsebyte(s); 87

88 Estos métodos son todos estáticos. Todas las clases además poseen métodos dinámicos para convertir a otros tipos (intvalue, longvalue,... o el conocido tostring). Todos estos métodos lanzan excepciones del tipo NumberFormatException, que habrá que capturar con el try y el catch pertinentes. Además han redefinido el método equals para comparar objetos de este tipo. Además poseen el método compareto que permite comparar dos elementos de este tipo. Algunos métodos de Integer. El constructor de un wrapper está sobrecargado para aceptar el tipo de dato primitivo que va a contener o un objeto String. Integer(int) Integer(String) Integer(int) Integer(String) Entre sus métodos encontramos algunos que nos permiten recuperar el tipo primitivo que queramos. doublevalue() floatvalue() longvalue() intvalue() shortvalue() bytevalue() También tenemos conversores con la clase String. String tostring() Integer valueof(string) 88

89 Además todos estos métodos pueden utilizarse en forma estática, esto es, no es necesario crear una instancia para utilizarlos. Aunque esto no es del todo cierto, ya que por ejemplo como sucede con el método valueof(), retorna una instancia del wrapper. Por lo tanto estas clases wrapper son fabricantes de objetos (ver factory pattern). Estas clases también declaran constantes que definen su valor máximo, su valor mínimo, etc. Conversiones entre distintos tipos de datos básicos He creado esta clase para conversiones con el fin de agrupar estos métodos y mostrar los simples pasos de conversión que debemos seguir. Básicamente el procedimiento en cada uno de los métodos es el mismo: crear una instancia del wrapper del argumento, con el valor de dicho argumento, y luego solicitar el tipo de dato primitivo a retornar por el método de conversión. final class Cast { /*float a int*/ public static int toint(float f) { int i; i = Float.valueOf(f).intValue(); return i; /*double a int*/ public static int toint(double d) { int i; i = Double.valueOf(d).intValue(); return i; /*int a double*/ 89

90 public static double todouble(int i) { double d; d = Integer.valueOf(i).doubleValue(); return d; /*String a double*/ public static double todouble(string s) { double d; d = Double.valueOf(s).doubleValue(); return d; /*float a String*/ public static String tostring(float f) { String s; s = Float.valueOf(f).toString(); return s; Si bien esta clase está incompleta (le faltarían muchos métodos más para ampliar su utilidad) podemos hacer un ejemplo y ver como trabaja. int i; float f; double d; String s = "9.543"; d = Cast.toDouble(s); // d = i = Cast.toInt(d); // i = 9 f = i; // f = 9.0 s = Cast.toString(f); // s = "9.0" 90

91 En conclusión estas clases son muy valiosas, aprender a utilizarlas es muy facil (sus métodos son muy similares, recuerden que derivan de Number) y nos proveen de la funcionalidad extra que se necesita. La clase String Para Java las cadenas de texto son objetos especiales. Los textos deben manejarse creando objetos de tipo String. Ejemplo: String texto1 = Prueba de texto! ; Las cadenas pueden ocupar varias líneas utilizando el operador de concatenación +. String texto2 = Este es un texto que ocupa + varias líneas, no obstante se puede + perfectamente encadenar ; También se pueden crear objetos String sin utilizar constantes entrecomilladas, usando otros constructores: char[] palabra = { P, a, l, b, r, a ;//Array de char String cadena = new String(palabra); byte[] datos = {97,98,99; String codificada = new String (datos, 8859_1 ); En el último ejemplo la cadena codificada se crea desde un array de tipo byte que contiene números que serán interpretados como códigos Unicode. Al asignar, el valor 8859_1 indica la tabla de códigos a utilizar. Comparación Entre Objetos String Los objetos String no pueden compararse directamente con los operadores de comparación. En su lugar se deben utilizar estas expresiones: 91

92 cadena1.equals(cadena2). El resultado es true si la cadena1 es igual a la cadena2. Ambas cadenas son variables de tipo String. cadena1.equalsignorecase(cadena2). Como la anterior, pero en este caso no se tienen en cuentas mayúsculas y minúsculas. s1.compareto(s2). Compara ambas cadenas, considerando el orden alfabético. Si la primera cadena es mayor en orden alfabético que la segunda devuelve 1, si son iguales devuelve 0 y si es la segunda la mayor devuelve -1. Hay que tener en cuenta que el orden no es el del alfabeto español, sino que usa la tabla ASCII, en esa tabla la letra ñ es mucho mayor que la o. s1.comparetoignorecase(s2). Igual que la anterior, sólo que además ignora las mayúsculas (disponible desde Java 1.2) String.valueOf Este método pertenece no sólo a la clase String, sino a otras y siempre es un método que convierte valores de una clase a otra. En el caso de los objetos String, permite convertir valores que no son de cadena a forma de cadena. Ejemplos: String numero = String.valueOf(1234); String fecha = String.valueOf(new Date()); En el ejemplo se observa que este método pertenece a la clase String directamente, no hay que utilizar el nombre del objeto creado (como se verá más adelante, es un método estático). Métodos De Las Variables De Cadena Son métodos que poseen las propias variables de cadena. Para utilizarlos basta con poner el nombre del método y sus parámetros después del nombre de la variable String. Es decir: variablestring.método(argumentos) length 92

93 Permite devolver la longitud de una cadena (el número de caracteres de la cadena): String texto1= Prueba ; System.out.println(texto1.length());//Escribe 6 Concatenar Cadenas Se puede hacer de dos formas, utilizando el método concat o con el operador +. Ejemplo: charat String s1= Buenos, s2= días, s3, s4; s3 = s1 + s2; s4 = s1.concat(s2); Devuelve un carácter de la cadena. El carácter a devolver se indica por su posición (el primer carácter es la posición 0) Si la posición es negativa o sobrepasa el tamaño de la cadena, ocurre un error de ejecución, una excepción tipo IndexOutOfBounds-Exception. Ejemplo: substring String s1= Prueba ; char c1=s1.charat(2); //c1 valdrá u Da como resultado una porción del texto de la cadena. La porción se toma desde una posición inicial hasta una posición final (sin incluir esa posición final). Si las posiciones indicadas no son válidas ocurre una excepción de tipo IndexOutOfBounds-Exception. Se empieza a contar desde la posición 0. Ejemplo: indexof String s1= Buenos días ; String s2=s1.substring(7,10); //s2 = día 93

94 Devuelve la primera posición en la que aparece un determinado texto en la cadena. En el caso de que la cadena buscada no se encuentre, devuelve -1. El texto a buscar puede ser char o String. Ejemplo: String s1= Quería decirte que quiero que te vayas ; System.out.println(s1.indexOf( que )); //Da 15 Se puede buscar desde una determinada posición. En el ejemplo anterior: System.out.println(s1.indexOf( que,16)); //Ahora da 26 lastindexof Devuelve la última posición en la que aparece un determinado texto en la cadena. Es casi idéntica a la anterior, sólo que busca desde el final. Ejemplo: String s1= Quería decirte que quiero que te vayas ; System.out.println(s1.lastIndexOf( que ); //Da 26 También permite comenzar a buscar desde una determinada posición. endswith Devuelve true si la cadena termina con un determinado texto. Ejemplo: startswith String s1= Quería decirte que quiero que te vayas ; System.out.println(s1.endsWith( vayas ); //Da true Devuelve true si la cadena empieza con un determinado texto. replace Cambia todas las apariciones de un carácter por otro en el texto que se indique y lo almacena como resultado. El texto original no se cambia, por lo que hay que asignar el resultado de replace a un String para almacenar el texto cambiado: String s1= Mariposa ; System.out.println(s1.replace( a, e ));//Da Meripose System.out.println(s1);//Sigue valiendo Mariposa 94

95 replaceall Modifica en un texto cada entrada de una cadena por otra y devuelve el resultado. El primer parámetro es el texto que se busca (que puede ser una expresión regular), el segundo parámetro es el texto con el que se reemplaza el buscado. La cadena original no se modifica. String s1= Cazar armadillos ; System.out.println(s1.replace( ar, er ));//Da Cazer ermedillos System.out.println(s1);//Sigue valiendo Cazar armadilos touppercase Devuelve la versión en mayúsculas de la cadena. tolowercase Devuelve la versión en minúsculas de la cadena. tochararray Obtiene un array de caracteres a partir de una cadena. La clase Arrays En el paquete java.utils se encuentra una clase estática llamada Arrays. Una clase estática permite ser utilizada como si fuera un objeto (como ocurre con Math). Esta clase posee métodos muy interesantes para utilizar sobre arrays. Su uso es fill Arrays.método(argumentos); Permite rellenar todo un array unidimensional con un determinado valor. Sus argumentos son el array a rellenar y el valor deseado: int valores[]=new int[23]; Arrays.fill(valores,-1);//Todo el array vale -1 También permite decidir desde que índice hasta qué índice rellenamos: Arrays.fill(valores,5,8,-1);//Del elemento 5 al 7 valdrán -1 95

96 equals Compara dos arrays y devuelve true si son iguales. Se consideran iguales si son del mismo tipo, tamaño y contienen los mismos valores. sort Permite ordenar un array en orden ascendente. Se pueden ordenar sólo una serie de elementos desde un determinado punto hasta un determinado punto. int x[]={4,5,2,3,7,8,2,3,9,5; Arrays.sort(x);//Estará ordenado Arrays.sort(x,2,5);//Ordena del 2º al 4º elemento binarysearch Permite buscar un elemento de forma ultrarrápida en un array ordenado (en un array desordenado sus resultados son impredecibles). Devuelve el índice en el que está colocado el elemento. Ejemplo: int x[]={1,2,3,4,5,6,7,8,9,10,11,12; Arrays.sort(x); System.out.println(Arrays.binarySearch(x,8));//Da 7 El método System.arraysCopy La clase System también posee un método relacionado con los arrays, dicho método permite copiar un array en otro. Recibe cinco argumentos: el array que se copia, el índice desde que se empieza a copia en el origen, el array destino de la copia, el índice desde el que se copia en el destino, y el tamaño de la copia (número de elementos de la copia). int uno[]={1,1,2; int dos[]={3,3,3,3,3,3,3,3,3; System.arraycopy(uno, 0, dos, 0, uno.length); for (int i=0;i<=8;i++){ System.out.print(dos[i]+" "); //Sale

97 Arrays Unidimensionales Un array es una colección de valores de un mismo tipo engrosados en la misma variable. De forma que se puede acceder a cada valor independientemente. Para Java además un array es un objeto que tiene propiedades que se pueden manipular. Los arrays solucionan problemas concernientes al manejo de muchas variables que se refieren a datos similares. Por ejemplo si tuviéramos la necesidad de almacenar las notas de una clase con 18 alumnos, necesitaríamos 18 variables, con la tremenda lentitud de manejo que supone eso. Solamente calcular la nota media requeriría una tremenda línea de código. Almacenar las notas supondría al menos 18 líneas de código. Gracias a los arrays se puede crear un conjunto de variables con el mismo nombre. La diferencia será que un número (índice del array) distinguirá a cada variable. En el caso de las notas, se puede crear un array llamado notas, que representa a todas las notas de la clase. Para poner la nota del primer alumno se usaría notas[0], el segundo sería notas[1], etc. (los corchetes permiten especificar el índice en concreto del array). La declaración de un array unidimensional se hace con esta sintaxis. tipo nombre[]; Ejemplo: double cuentas[]; //Declara un array que almacenará valores doubles Declara un array de tipo double. Esta declaración indica para qué servirá el array, pero no reserva espacio en la RAM al no saberse todavía el tamaño del mismo. Tras la declaración del array, se tiene que iniciar. Eso lo realiza el operador new, que es el que realmente crea el array indicando un tamaño. Cuando 97

98 se usa new es cuando se reserva el espacio necesario en memoria. Un array no inicializado es un array null. Ejemplo: int notas[]; //sería válido también int[] notas; notas = new int[3]; //indica que el array constará de tres //valores de tipo int //También se puede hacer todo a la vez //int notas[]=new int[3]; En el ejemplo anterior se crea un array de tres enteros (con los tipos básicos se crea en memoria el array y se inicializan los valores, los números se inician a 0). Los valores del array se asignan utilizando el índice del mismo entre corchetes: notas[2]=8; También se pueden asignar valores al array en la propia declaración: int notas[] = {8, 7, 9; int notas2[]= new int[] {8,7,9;//Equivalente a la anterior Esto declara e inicializa un array de tres elementos. En el ejemplo lo que significa es que notas[0] vale 8, notas[1] vale 7 y notas[2] vale 9. En Java (como en otros lenguajes) el primer elemento de un array es el cero. El primer elemento del array notas, es notas[0]. Se pueden declarar arrays a cualquier tipo de datos (enteros, booleanos, doubles,... e incluso objetos). La ventaja de usar arrays (volviendo al caso de las notas) es que gracias a un simple bucle for se puede rellenar o leer fácilmente todos los elementos de un array: //Calcular la media de las 18 notas suma=0; for (int i=0;i<=17;i++){ suma+=nota[i]; 98

99 media=suma/18; A un array se le puede inicializar las veces que haga falta: int notas[]=new notas[16];... notas=new notas[25]; Pero hay que tener en cuenta que el segundo new hace que se pierda el contenido anterior. Realmente un array es una referencia a valores que se almacenan en memoria mediante el operador new, si el operador new se utiliza en la misma referencia, el anterior contenido se queda sin referencia y, por lo tanto se pierde. Un array se puede asignar a otro array (si son del mismo tipo): int notas[]; int ejemplo[]=new int[18]; notas=ejemplo; En el último punto, notas equivale a ejemplo. Esta asignación provoca que cualquier cambio en notas también cambie el array ejemplos. Es decir esta asignación anterior, no copia los valores del array, sino que notas y ejemplo son referencias al mismo array. Ejemplo: int notas[]={3,3,3; int ejemplo[]=notas; ejemplo= notas; ejemplo[0]=8; System.out.println(notas[0]);//Escribirá el número 8 Arrays Multidimensionales Los arrays además pueden tener varias dimensiones. Entonces se habla de arrays de arrays (arrays que contienen arrays) Ejemplo: int notas[][]; 99

100 notas es un array que contiene arrays de enteros notas = new int[3][12];//notas está compuesto por 3 arrays //de 12 enteros cada uno notas[0][0]=9;//el primer valor es 0 Puede haber más dimensiones incluso (notas[3][2][7]). Los arrays multidimensionales se pueden inicializar de forma más creativa incluso. Ejemplo: int notas[][]=new int[5][];//hay 5 arrays de enteros notas[0]=new int[100]; //El primer array es de 100 enteros notas[1]=new int[230]; //El segundo de 230 notas[2]=new int[400]; notas[3]=new int[100]; notas[4]=new int[200]; Hay que tener en cuenta que en el ejemplo anterior, notas[0] es un array de 100 enteros. Mientras que notas, es un array de 5 arrays de enteros. Se pueden utilizar más de dos dimensiones si es necesario. Longitud De Un Array Los arrays poseen un método que permite determinar cuánto mide un array. Se trata de length. Ejemplo (continuando del anterior): System.out.println(notas.length); //Sale 5 System.out.println(notas[2].length); //Sale 400 La clase Math. Se echan de menos operadores matemáticos más potentes en Java. Por ello se ha incluido una clase especial llamada Math dentro del paquete java.lang Para poder utilizar esta clase, se debe incluir esta instrucción: import java.lang.math; Esta clase posee métodos muy interesantes para realizar cálculos matemáticos complejos. Por ejemplo: double x= Math.pow(3,3); //x es 27 Math posee dos constantes, que son: 100

101 Math.E para la base exponencial, aproximadamente 2.72 Math.PI para PI, aproximadamente 3.14 Por otro lado posee numerosos métodos que son: Método Math.abs( x ) Math.sin( double a ) Math.cos( double a ) Math.tan( double a ) Descripción Para int, long, float y double. Devuelve el seno del ángulo a en radianes. Devuelve el coseno del ángulo a en radianes. Devuelve la tangente del ángulo a en radianes. Math.asin( double r ) Devuelve el ángulo cuyo seno es r. Math.acos( double r ) Devuelve el ángulo cuyo coseno es r. Math.atan( double r ) Devuelve el ángulo cuya tangente es Math.atan2(double a,double b) r. Devuelve el ángulo cuya tangente es a/b. Math.exp( double x ) Devuelve e elevado a x. Math.log( double x ) Devuelve el logaritmo natural de x. Math.sqrt( double x ) Devuelve la raíz cuadrada de x. Math.ceil( double a ) Devuelve el número completo más Math.floor( double a ) Math.rint( double a ) pequeño mayor o igual que a. Devuelve el número completo más grande menor o igual que a. Devuelve el valor double truncado de a Math.pow( double x,double y ) Devuelve x elevado a y. Math.round( x ) Para double y float. Math.random() Devuelve un double entre 0 y 1. Math.max( a,b ) Para int, long, float y double. Math.min( a,b ) Para int, long, float y double. COLECCIONES. Estructuras estáticas de datos y estructuras dinámicas En prácticamente todos los lenguajes de computación existen estructuras para almacenar colecciones de datos. Esto es una serie de datos agrupados a los que se puede hacer referencia con un único nombre. Ejemplo de ello son los arrays. El problema del uso de los arrays es que es una estructura estática, esto significa que se debe saber el número de elementos que formarán parte de esa 101

102 colección a priori, es decir en tiempo de compilación hay que decidir el tamaño de un array. Las estructuras dinámicas de datos tienen la ventaja de que sus integrantes se deciden en tiempo de ejecución y que el número de elementos es ilimitado. Estas estructuras dinámicas son clásicas en la programación y son las colas, pilas, listas enlazadas, árboles, grafos, etc. En muchos lenguajes se implementan mediante punteros; como Java no posee punteros se crearon clases especiales para implementar estas funciones. En Java desde la primera versión se incluyeron las clases: vector, Stack, Hashtable, BitSet y la interfaz Enumeration. En Java 2 se modificó este funcionamiento y se potenció la creación de estas clases. Trabajo con Colecciones Cuando se necesitan características más sofisticadas para almacenar objetos, que las que proporciona un simple array, Java pone a disposición las clases colección: Vector, BitSet, Stack y Hashtable. Entre otras características, las clases colección se redimensionan automáticamente, por lo que se puede colocar en ellas cualquier número de objetos, sin necesidad de tener que ir controlando continuamente en el programa la longitud de la colección. La gran desventaja del uso de las colecciones en Java es que se pierde la información de tipo cuando se coloca un objeto en una colección. Esto ocurre porque cuando se escribió la colección, el programador de esa colección no tenía ni idea del tipo de datos específicos que se iban a colocar en ella, y teniendo en mente el hacer una herramienta lo más general posible, se hizo que manejase directamente objetos de tipo Object, que es el objeto raíz de todas las clases en Java. La solución es perfecta, excepto por dos razones: 1. Como la información de tipo se pierde al colocar un objeto en la colección, cualquier tipo de objeto se va a poder colar en ella, es decir, si la colección está destinada a contener animales mamíferos, nada impide que se pueda colar un coche en ella. 102

103 2. Por la misma razón de la pérdida de tipo, la única cosa que sabe la colección es que maneja un Object. Por ello, hay que colocar siempre un moldeo al tipo adecuado antes de utilizar cualquier objeto contenido en una colección. La verdad es que no todo es tan negro, Java no permite que se haga uso inadecuado de los objetos que se colocan en una colección. Si se introduce un coche en una colección de animales mamíferos, al intentar extraer el coche se obtendrá una excepción. Y del mismo modo, si se intenta colocar un moldeo al coche que se está sacando de la colección para convertirlo en animal mamífero, también se obtendrá una excepción en tiempo de ejecución. Ejemplo # import java.util.*; class Coche { private int numcoche; Coche( int i ) { numcoche = i; void print() { System.out.println( "Coche #"+numcoche ); class Barco { private int numbarco; Barco( int i ) { numbarco = i; void print() { System.out.println( "Barco #"+numbarco ); 103

104 public class java411 { public static void main( String args[] ) { Vector coches = new Vector(); for( int i=0; i < 7; i++ ) coches.addelement( new Coche( i ) ); //No hay ningun problema en añadir un barco a los coches coches.addelement( new Barco( 7 ) ); for( int i=0; i < coches.size(); i++ ) (( Coche )coches.elementat( i ) ).print(); //El barco solamente es detectado en tiempo de ejecucion Como se puede observar, el uso de un Vector es muy sencillo: se crea uno, se colocan elementos en él con el método addelement() y se recuperan con el método elementat(). Vector tiene el método size() que permite conocer cuántos elementos contiene, para evitar el acceso a elementos fuera de los límites del Vector y obtener una excepción. Las clases Coche y Barco son distintas, no tienen nada en común excepto que ambas son Object. Si no se indica explícitamente de la clase que se está heredando, automáticamente se hereda de Object. La clase Vector maneja elementos de tipo Object, así que no solamente es posible colocar en ella objetos Coche utilizando el método addelement(), sino que también se pueden colocar elementos de tipo Barco sin que haya ningún problema ni en tiempo de compilación ni a la hora de ejecutar el programa. Cuando se recupere un objeto que se supone es un Coche utilizando el método elementat() de la clase Vector, hay que colocar un moldeo para convertir el objeto Object en el Coche que se espera, luego hay que colocar toda la expresión entre paréntesis para forzar la evaluación del moldeo antes de llamar al método print() de la clase Coche, sino habrá un error de sintaxis. Posteriormente, ya en tiempo de ejecución, cuando se 104

105 intente moldear un objeto Barco a un Coche, se generará una excepción, tal como se puede comprobar en las siguientes líneas, que reproducen la salida de la ejecución del ejemplo: %java java411 Coche #0 Coche #1 Coche #2 Coche #3 Coche #4 Coche #5 Coche #6 java.lang.classcastexception: Barco at java411.main(java411.java:54) Lo cierto es que esto es un fastidio, porque puede ser la fuente de errores que son muy difíciles de encontrar. Si en una parte, o en varias partes, del programa se insertan elementos en la colección, y se descubre en otra parte diferente del programa que se genera una excepción es porque hay algún elemento erróneo en la colección, así que hay que buscar el sitio donde se ha insertado el elemento de la discordia, lo cual puede llevar a intensas sesiones de depuración. Así que, para enredar al principio, es mejor empezar con clases estandarizadas en vez de aventurarse en otras más complicadas, a pesar de que estén menos optimizadas. Jerarquia de Colecciones 105

106 Enumeraciones En cualquier clase de colección, debe haber una forma de meter cosas y otra de sacarlas; después de todo, la principal finalidad de una colección es almacenar cosas. En un Vector, el método addelement() es la manera en que se colocan objetos dentro de la colección y llamando al método elementat() es cómo se sacan. Vector es muy flexible, se puede seleccionar cualquier cosa en cualquier momento y seleccionar múltiples elementos utilizando diferentes índices. Si se quiere empezar a pensar desde un nivel más alto, se presenta un inconveniente: la necesidad de saber el tipo exacto de la colección para utilizarla. Esto no parece que sea malo en principio, pero si se empieza implementando un Vector a la hora de desarrollar el programa, y posteriormente se decide cambiarlo a List, por eficiencia, entonces sí es problemático. El concepto de enumerador, o iterador, que es su nombre más común en C++ y OOP, puede utilizarse para alcanzar el nivel de abstracción que se necesita en este caso. Es un objeto cuya misión consiste en moverse a través de una secuencia de objetos y seleccionar aquellos objetos adecuados sin que el 106

107 programador cliente tenga que conocer la estructura de la secuencia. Además, un iterador es normalmente un objeto ligero, lightweight, es decir, que consumen muy pocos recursos, por lo que hay ocasiones en que presentan ciertas restricciones; por ejemplo, algunos iteradores solamente se puede mover en una dirección. La Enumeration en Java es un ejemplo de un iterador con esas características, y las cosas que se pueden hacer son: o o o Crear una colección para manejar una Enumeration utilizando el método elements(). Esta Enumeration estará lista para devolver el primer elemento en la secuencia cuando se llame por primera vez al método nextelement(). Obtener el siguiente elemento en la secuencia a través del método nextelement(). Ver si hay más elementos en la secuencia con el método hasmoreelements(). Y esto es todo. No obstante, a pesar de su simplicidad, alberga bastante poder. Para ver cómo funciona, el ejemplo java412.java, es la modificación de anterior, en que se utilizaba el método elementat() para seleccionar cada uno de los elementos. Ahora se utiliza una enumeración para el mismo propósito, y el único código interesante de este nuevo ejemplo es el cambio de las líneas del ejemplo original for( int i=0; i < coches.size(); i++ ) (( Coche )coches.elementat( i ) ).print(); Por estas otras en que se utiliza la enumeración para recorrer la secuencia de objetos while( e.hasmoreelements() ) (( Coche )e.nextelement()).print(); Con la Enumeration no hay que preocuparse del número de elementos que contenga la colección, ya que del control sobre ellos se encargan los métodos hasmoreelements() y nextelement(). 107

108 Tipos de Colecciones Con el JDK 1.0 y 1.1 se proporcionaban librerías de colecciones muy básicas, aunque suficientes para la mayoría de los proyectos. En el JDK 1.2 en adelante ya se amplía esto y, además, las anteriores colecciones han sufrido un profundo rediseño. A continuación se verán cada una de ellas por separado para dar una idea del potencial que se ha incorporado a Java. Vector El Vector es muy simple y fácil de utilizar. Aunque los métodos más habituales en su manipulación son addelement() para insertar elementos en el Vector, elementat() para recuperarlos y elements() para obtener una Enumeration con el número de elementos del Vector, lo cierto es que hay más métodos, pero no es el momento de relacionarlos todos, así que, al igual que sucede con todas las librerías de Java, se remite al lector a que consulte la documentación electrónica que proporciona Javasoft, para conocer los demás métodos que componen esta clase. Las colecciones estándar de Java contienen el método tostring(), que permite obtener una representación en forma de String de sí mismas, incluyendo los objetos que contienen. Dentro de Vector, por ejemplo, tostring() va saltando a través de los elementos del Vector y llama al método tostring() para cada uno de esos elementos. En caso, por poner un ejemplo, de querer imprimir la dirección de la clase, parecería lógico referirse a ella simplemente como this (los programadores C++ estarán muy inclinados a esta posibilidad), así que tendríamos el código que muestra el ejemplo java413.java y que se reproduce en las siguientes líneas. import java.util.*; public class java413 { public String tostring() { return( "Direccion del objeto: "+this+"\n" ); 108

109 public static void main( String args[] ) { Vector v = new Vector(); for( int i=0; i < 10; i++ ) v.addelement( new java413() ); System.out.println( v ); El ejemplo no puede ser más sencillo, simplemente crea un objeto de tipo java413 y lo imprime; sin embargo, a la hora de ejecutar el programa lo que se obtiene es una secuencia infinita de excepciones. Lo que está pasando es que cuando se le indica al compilador: "Direccion del objeto: "+this El compilador ve un String seguido del operador + y otra cosa que no es un String, así que intenta convertir this en un String. La conversión la realiza llamando al método tostring() que genera una llamada recursiva, llegando a llenarse la pila. Si realmente se quiere imprimir la dirección del objeto en este caso, la solución pasa por llamar al método tostring() de la clase Object. Así, si en vez de this se coloca super.tostring(), el ejemplo funcionará. En otros casos, este método también funcionará siempre que se esté heredando directamente de Object o, aunque no sea así, siempre que ninguna clase padre haya sobreescrito el método tostring(). BitSet Se llama así lo que en realidad es un Vector de bits. Lo que ocurre es que está optimizado para uso de bits. Bueno, optimizado en cuanto a tamaño, porque en lo que respecta al tiempo de acceso a los elementos, es bastante más lento que el acceso a un array de elementos del mismo tipo básico. 109

110 Además, el tamaño mínimo de un BitSet es de 64 bits. Es decir, que si se está almacenando cualquier otra cosa menor, por ejemplo de 8 bits, se estará desperdiciando espacio. En un Vector normal, la colección se expande cuando se añaden más elementos. En el BitSet ocurre los mismo pero ordenadamente. El ejemplo java414.java, muestra el uso de esta colección. Se utiliza el generador de números aleatorios para obtener un byte, un short y un int, que son convertidos a su patrón de bits e incorporados al BitSet. Stack Un Stack es una Pila, o una colección de tipo LIFO (last-in, first-out). Es decir, lo último que se coloque en la pila será lo primero que se saque. Como en todas las colecciones de Java, los elementos que se introducen y sacan de la pila son Object, así que hay que tener cuidado con el moldeo a la hora de sacar alguno de ellos. Los diseñadores de Java, en vez de utilizar un Vector como bloque para crear un Stack, han hecho que Stack derive directamente de Vector, así que tiene todas las características de un Vector más alguna otra propia ya del Stack. El ejemplo siguiente, java415.java, es una demostración muy simple del uso de una Pila que consisten en leer cada una de las líneas de un array y colocarlas en un String. Cada línea en el array diassemana se inserta en el Stack con push() y posteriormente se retira con pop(). Para ilustrar una afirmación anterior, también se utilizan métodos propios de Vector sobre el Stack. Esto es posible ya que en virtud de la herencia un Stack es un Vector, así que todas las operaciones que se realicen sobre un Vector también se podrán realizar sobre un Stack, como por ejemplo, elementat(). 110

111 Hashtable Un Vector permite selecciones desde una colección de objetos utilizando un número, luego parece lógico pensar que hay números asociados a los objetos. Bien, entonces qué es lo que sucede cuando se realizan selecciones utilizando otros criterios? Un Stack podría servir de ejemplo: su criterio de selección es "lo último que se haya colocado en el Stack". Si rizamos la idea de "selección desde una secuencia", nos encontramos con un mapa, un diccionario o un array asociativo. Conceptualmente, todo parece ser un vector, pero en lugar de acceder a los objetos a través de un número, en realidad se utiliza otro objeto. Esto nos lleva a utilizar claves y al procesado de claves en el programa. Este concepto se expresa en Java a través de la clase abstracta Dictionary. El interfaz para esta clase es muy simple: size(), indica cuántos elementos contiene, isempty(), es true si no hay ningún elemento, put( Object clave,object valor), añade un valor y lo asocia con una clave get( Object clave ), obtiene el valor que corresponde a la clave que se indica remove( Object clave ), elimina el par clave-valor de la lista keys(), genera una Enumeration de todas las claves de la lista elements(), genera una Enumeration de todos los valores de la lista Todo es lo que corresponde a un Diccionario (Dictionary), que no es excesivamente difícil de implementar. El ejemplo java416.java es una aproximación muy simple que utiliza dos Vectores, uno para las claves y otro para los valores que corresponden a esas claves. 111

112 import java.util.*; public class java416 extends Dictionary { private Vector claves = new Vector(); private Vector valores = new Vector(); public int size() { return( claves.size() ); public boolean isempty() { return( claves.isempty() ); public Object put( Object clave,object valor ) { claves.addelement( clave ); valores.addelement( valor ); return( clave ); public Object get( Object clave ) { int indice = claves.indexof( clave ); // El metodo indexof() devuelve -1 // si no encuentra la clave que se // esta buscando if( indice == -1 ) return( null ); return( valores.elementat( indice ) ); public Object remove(object clave) { int indice = claves.indexof( clave ); if( indice == -1 ) return( null ); 112

113 claves.removeelementat( indice ); Object valorretorno = valores.elementat( indice ); valores.removeelementat( indice ); return( valorretorno ); public Enumeration keys() { return( claves.elements() ); public Enumeration elements() { return( valores.elements() ); ; // Ahora es cuando se prueba el ejemplo public static void main( String args[] ) { java416 ej = new java416(); for( char c='a'; c <= 'z'; c++ ) ej.put( String.valueOf( c ),String.valueOf( c ).touppercase() ) char[] vocales = { 'a','e','i','o','u' ; for( int i=0; i < vocales.length; i++ ) System.out.println( "Mayusculas: " + ej.get( String.valueOf( vocales[i] ) ) ); La primera cosa interesante que se puede observar en la definición de java416 es que extiende a Dictionary. Esto significa que java416 es un tipo de Diccionario, con lo cual se pueden realizar las mismas peticiones y llamar a los mismos métodos que a un Diccionario. A la hora de construirse un Diccionario propio todo lo que se necesita es rellenar todos 113

114 los métodos que hay en Dictionary. Se deben sobreescribir todos ellos, excepto el constructor, porque todos son abstractos. Los Vectores claves y valores están relacionados a través de un número índice común. Es decir, si se llama al método put() con la clave "león" y el valor "rugido" en la asociación de animales con el sonido que producen, y ya hay 100 elementos en la clase java416, entonces "león" será el elemento 101 de claves y "rugido" será el elemento 101 de valores. Y cuando se pasa al método get() como parámetro "león", genera el número índice con claves.indexof(), y luego utiliza este índice para obtener el valor asociado en el vector valores. Para mostrar el funcionamiento, en main() se utiliza algo tan simple como mapear las letras minúsculas y mayúsculas, que aunque se pueda hacer de otras formas más eficientes, sí sirve para mostrar el funcionamiento de la clase, que es lo que se pretende por ahora. La librería estándar de Java solamente incorpora una implementación de un Dictionary, la Hashtable. Esta Hashtable tiene el mismo interfaz básico que la clase del ejemplo anterior java416, ya que ambas heredan de Dictionary, pero difiere en algo muy importante: la eficiencia. Si en un Diccionario se realiza un get() para obtener un valor, se puede observar que la búsqueda es bastante lenta a través del vector de claves. Aquí es donde la Hashtable acelera el proceso, ya que en vez de realizar la tediosa búsqueda línea a línea a través del vector de claves, utiliza un valor especial llamado código hash. El código hash es una forma de conseguir información sobre el objeto en cuestión y convertirlo en un int relativamente único para ese objeto. Todos los objetos tienen un código hash y hashcode() es un método de la clase Object. Una Hashtable coge el hashcode() del objeto y lo utiliza para cazar rápidamente la clave. El resultado es una impresionante reducción del tiempo de búsqueda. La tabla Hash es un Diccionario muy rápido y que un Diccionario es una herramienta muy útil. 114

115 Para ver el funcionamiento de la tabla Hash está el ejemplo java417.java, que intenta comprobar la aleatoriedad del método Math.random(). Idealmente, debería producir una distribución perfecta de números aleatorios, pero para poder comprobarlo sería necesario generar una buena cantidad de números aleatorios y comprobar los rangos en que caen. Una Hashtable es perfecta para este propósito al asociar objetos con objetos, en este caso, los valores producidos por el método Math.random() con el número de veces en que aparecen esos valores. import java.util.*; class Contador { int i = 1; public String tostring() { return( Integer.toString( i ) ); class java417 { public static void main( String args[] ) { Hashtable ht = new Hashtable(); for( int i=0; i < 10000; i++ ) { // Genera un número cuasi-aleatorio entre 0 y 20 Integer r = new Integer( (int)( Math.random()*20 ) ); if( ht.containskey( r ) ) else ( (Contador)ht.get( r ) ).i++; ht.put( r,new Contador() ); System.out.println( ht ); 115

116 En el método main() del ejemplo, cada vez que se genera un número aleatorio, se convierte en objeto Integer para que pueda ser manejado por la tabla Hash, ya que no se pueden utilizar tipos básicos con una colección, porque solamente manejan objetos. El método containskey() comprueba si la clave se encuentra ya en la colección. En caso afirmativo, el método get() obtiene el valor asociado a la clave, que es un objeto de tipo Contador. El valor i dentro del contador se incrementa para indicar que el número aleatorio ha aparecido una vez más. Si la clave no se encuentra en la colección, el método put() colocará el nuevo par clave-valor en la tabla Hash. Como Contador inicializa automáticamente su variable i a 1 en el momento de crearla, ya se indica que es la primera vez que aparece ese número aleatorio concreto. Para presentar los valores de la tabla Hash, simplemente se imprimen. El método tostring() de Hashtable navega a través de los pares clave-valor y llama a método tostring() de cada uno de ellos. El método tostring() de Integer está predefinido, por lo que no hay ningún problema en llamar a tostring() para Contador. Un ejemplo de ejecución del programa sería la salida que se muestra a continuación: %java java417 {19=526, 18=533, 17=460, 16=513, 15=521, 14=495, 13=512, 12=483, 11=488, 10=487, 9=514, 8=523, 7=497, 6=487, 5=489, 3=509, 2=503, 1=475, 0=505 Al lector le puede parecer superfluo el uso de la clase Contador, que parece que no hace nada que no haga ya la clase Integer. Por qué no utilizar int o Integer? Pues bien, int no puede utilizarse porque como ya se ha indicado antes, las colecciones solamente manejan objetos, por ello están las clases que envuelven a esos tipos básicos y los convierten en objetos. Sin embargo, la única cosa que pueden hacer estas clases es inicializar los objetos a un valor determinado y leer ese valor. Es decir, no 116

117 hay modo alguno de cambiar el valor de un objeto correspondiente a un tipo básico, una vez que se ha creado. Esto hace que la clase Integer sea inútil para resolver el problema que plantea el ejemplo, así que la creación de la clase Contador es imprescindible. Quizás ahora que el lector sabe que no puede colocar objetos creados a partir de las clases correspondientes a tipos básicos en colecciones, estas clases tengan un poco menos de valor, pero... la vida es así, por un lado da y por otro quita... y Java no va a ser algo diferente. En el ejemplo se utiliza la clase Integer, que forma parte de la librería estándar de Java como clave para la tabla Hash, y funciona perfectamente porque tiene todo lo necesario para funcionar como clave. Pero un error muy común se presenta a la hora de crear clases propias para que funcionen como claves. Por ejemplo, supóngase que se quiere implementar un sistema de predicción del tiempo en base a objetos de tipo Oso y tipo Prediccion, para detectar cuando entra la primavera. Tal como se muestra en el ejemplo java418.java, la cosa parece muy sencilla, se crean las dos clases y se utiliza Oso como clave y Prediccion como valor. Cada Oso tendrá un número de identificación, por lo que sería factible buscar una Prediccion en la tabla Hash de la forma: "Dime la Prediccion asociada con el Oso número 3". La clase Prediccion contiene un booleano que es inicializado utilizando Math.random(), y una llamada al método tostring() convierte el resultado en algo legible. En el método main(), se rellena una Hashtable con los Osos y sus Predicciones asociadas. Cuando la tabla Hash está completa, se imprime. Y ya se hace la consulta anterior sobre la tabla para buscar la Prediccion que corresponde al Oso número 3. Esto parece simple y suficiente, pero no funciona. El problema es que Oso deriva directamente de la clase raíz Object, que es lo que ocurre cuando no se especifica una clase base, que en última instancia se hereda de Object. Luego es el método hashcode() de Object el que se utiliza para generar el código hash para cada objeto que, por defecto, utiliza la dirección de ese objeto. Así, la primera instancia de Oso(3) no va a producir un código hash igual que producirá una segunda instancia de 117

118 Oso(3), con lo cual no se puede utilizar para obtener buenos resultados de la tabla. Se puede seguir pensando con filosofía ahorrativa y decir que todo lo que se necesita es sobreescribir el método hashcode() de la forma adecuada y ya está. Pero, esto tampoco va a funcionar hasta que se haga una cosa más: sobreescribir el método equals(), que también es parte de Object. Este es el método que utiliza la tabla Hash para determinar si la clave que se busca es igual a alguna de las claves que hay en la tabla. De nuevo, el método Object.equals() solamente compara direcciones de objetos, por lo que un Oso(3) probablemente no sea igual a otro Oso(3). Por lo tanto, a la hora de escribir clases propias que vayan a funcionar como clave en una Hastable, hay que sobreescribir los métodos hashcode() y equals(). El ejemplo java419.java ya se incorporan estas circunstancias. import java.util.*; // Si se crea una clase que utilice una clave en una Tabla Hash, es // imprescindible sobreescribir los metodos hashcode() y equals() // Utilizamos un oso para saber si está hibernando en su temporada de // invierno o si ya tine que despertarse porque le llega la primavera class Oso2 { int numero; Oso2( int n ) { numero = n; public int hashcode() { return( numero ); 118

119 public boolean equals( Object obj ) { if( (obj!= null) && (obj instanceof Oso2) ) else return( numero == ((Oso2)obj).numero ); return( false ); // En función de la oscuridad, o claridad del día, pues intenta saber si // ya ha la primavera ha asomado a nuestras puertas class Prediccion { boolean oscuridad = Math.random() > 0.5; public String tostring() { if( oscuridad ) else return( "Seis semanas mas de Invierno!" ); return( "Entrando en la Primavera!" ); public class java419 { public static void main(string args[]) { #3:"); Hashtable ht = new Hashtable(); for( int i=0; i < 10; i++ ) ht.put( new Oso2( i ),new Prediccion() ); System.out.println( "ht = "+ht+"\n" ); System.out.println( "Comprobando la prediccion para el oso Oso2 oso = new Oso2( 3 ); if( ht.containskey( oso ) ) System.out.println( (Prediccion)ht.get( oso ) ); 119

120 El método hashcode() devuelve el número que corresponde a un Oso como un identificador, siendo el programador el responsable de que no haya dos números iguales. El método hashcode() no es necesario que devuelva un identificador, sino que eso es necesario porque equals() debe ser capaz de determinar estrictamente cuando dos objetos son equivalentes. El método equals() realiza dos comprobaciones adicionales, una para comprobar si el objeto es null, y, en caso de que no lo sea, comprobar que sea una instancia de Oso, para poder realizar las comparaciones, que se basan en los números asignados a cada objeto Oso. Cuando se ejecuta este nuevo programa, sí se produce la salida correcta. Hay muchas clases de la librería de Java que sobreescriben los métodos hashcode() y equals() basándose en el tipo de objetos que son capaces de crear. Las tablas Hash son utilizadas también por muchas clases de la librería estándar de Java, por ejemplo, para obtener las propiedades del sistema se usa la clase Properties que hereda directamente de Hashtable. Y además, contiene una segunda Hashtable en donde guarda las propiedades del sistema que se usan por defecto. Para el autor, las colecciones son una de las herramientas más poderosas que se pueden poner en manos de un programador. Por ello, las colecciones que incorporaba Java, adolecían de precariedad y de demasiada rapidez en su desarrollo. Por todo ello, para quien escribe esto ha sido una tremenda satisfacción comprobar las nuevas colecciones que incorpora el JDK 1.2, y ver que incluso las antiguas han sido rediseñadas. Probablemente, las colecciones, junto con la librería Swing, son las dos cosas más importantes que aporta la versión 1.2 del JDK, y ayudarán enormemente a llevar a Java a la primera línea de los lenguajes de programación. Hay cambios de diseño que hacen su uso más simple. Por ejemplo, muchos nombres son más cortos, más claros y más fáciles de entender; e 120

121 incluso algunos de ellos han sido cambiados totalmente para adaptarse a la terminología habitual. El rediseño también incluye la funcionalidad, pudiendo encontrar ahora listas enlazadas y colas. El diseño de una librería de colecciones es complicado y difícil. En C++, la Standard Template Library (STL) cubría la base con muchas clases diferentes. Desde luego, esto es mejor que cuando no hay nada, pero es difícil de trasladar a Java porque el resultado llevaría a tal cantidad de clases que podría ser muy confuso. En el otro extremo, hay librerías de colecciones que constan de una sola clase, Collection, que actúa como un Vector y una Hashtable al mismo tiempo. Los diseñadores de las nuevas colecciones han intentado mantener un difícil equilibrio: por un lado disponer de toda la funcionalidad que el programador espera de una buena librería de colecciones, y, por otro, que sea tan fácil de aprender y utilizar como la STL y otras librerías similares. El resultado puede parecer un poco extraño en ocasiones, pero, al contrario que en las librerías anteriores al JDK 1.2, no son decisiones accidentales, sino que están tomadas a conciencia en función de la complejidad. Es posible que se tarde un poco en sentirse cómodo con algunos de los aspectos de la librería, pero de seguro que el programador intentará adoptar rápidamente estos nuevos métodos. Hay que reconocer que Joshua Bloch de Sun, ha hecho un magnífico trabajo en el rediseño de esta librería. La nueva librería de colecciones parte de la premisa de almacenar objetos, y diferencia dos conceptos en base a ello: Colección (Collection): un grupo de elementos individuales, siempre con alguna regla que se les puede aplicar. Una List almacenará objetos en una secuencia determinada y, un Set no permitirá elementos duplicados. Mapa (Map): un grupo de parejas de objetos clavevalor, como la Hastable ya vista. En principio podría parecer que esto es una Collection de parejas, pero cuando se intenta 121

122 implementar, este diseño se vuelve confuso, por lo que resulta mucho más claro tomarlo como un concepto separado. Además, es conveniente consultar porciones de un Map creando una Collection que represente a esa porción; de este modo, un Map puede devolver un Set de sus claves, una List de sus valores, o una List de sus parejas clave-valor. Los Mapas, al igual que los arrays, se pueden expandir fácilmente en múltiples dimensiones sin la incorporación de nuevos conceptos: simplemente se monta un Map cuyos valores son Mapas, que a su vez pueden estar constituidos por Mapas, etc. Las Colecciones y los Mapas pueden ser implementados de muy diversas formas, en función de las necesidades concretas de programación, por lo que puede resultar útil el siguiente diagrama de herencia de las nuevas colecciones que utiliza la notación gráfica propugnada por la metodología OMT (Object Modeling Technique). El diagrama está hecho a partir de la versión beta del JDK 1.2, así que puede haber cosas cambiadas con respecto a la versión final. Quizás también, un primer vistazo puede abrumar al lector, pero a lo largo de la sección se comprobará que es bastante simple, porque solamente hay tres colecciones: Map, List y Set; y solamente dos o tres implementaciones de cada una de ellas. Las cajas punteadas representan interfaces y las sólidas representan clases normales, excepto aquellas en que el texto interior comienza por Abstract, que representan clases abstractas. Las flechas indican que una clase puede generar objetos de la clase a la que apunta; por ejemplo, cualquier Collection puede producir un Iterator, mientras que una List puede producir un ListIterator (al igual que un Iterator normal, ya que List hereda de Collection). Los interfaces que tienen que ver con el almacenamiento de datos son: Collection, Set, List y Map. Normalmente, un programador creará casi todo su código para entenderse con estos interfaces y solamente necesitará indicar específicamente el tipo de datos que se están usando en el momento de la creación. Por ejemplo, una Lista se puede crear de la siguiente forma: List lista = new LinkedList(); 122

123 Desde luego, también se puede decidir que lista sea una lista enlazada, en vez de una lista genérica, y precisar más el tipo de información de la lista. Lo bueno, y la intención, del uso de interfaces es que si ahora se decide cambiar la implementación de la lista, solamente es necesario cambiar el punto de creación, por ejemplo: List lista = new ArrayList(); el resto del código permanece invariable. En la jerarquía de clases, se pueden ver algunas clases abstractas que pueden confundir en un principio. Son simplemente herramientas que implementan parcialmente un interfaz. Si el programador quiere hacer su propio Set, por ejemplo, no tendría que empezar con el interfaz Set e implementar todos los métodos, sino que podría derivar directamente de AbstractSet y ya el trabajo para crear la nueva clase es mínimo. Sin embargo, la nueva librería de colecciones contiene suficiente funcionalidad para satisfacer casi cualquier necesidad, así que en este Tutorial se ignorarán las clases abstractas. Por lo tanto, a la hora de sacar provecho del diagrama es suficiente con lo que respecta a los interfaces y a las clases concretas. Lo normal será construir un objeto correspondiente a una clase concreta, moldearlo al correspondiente interfaz y ya usas ese interfaz en el resto del código. El ejemplo java420.java es muy simple y consiste en una colección de objetos String que se imprimen. import java.util.*; public class java420 { public static void main( String args[] ) { Collection c = new ArrayList(); for( int i=0; i < 10; i++ ) c.add( Integer.toString( i ) ); Iterator it = c.iterator(); while( it.hasnext() ) System.out.println( it.next() ); 123

124 Colecciones Como las nuevas colecciones forman parte del paquete java.util, no es necesario importar ningún paquete adicional para utilizarlas. A continuación se comentan los trozos interesantes del código del ejemplo. La primera línea del método main() crea un objeto ArrayList y lo moldea a una Collection. Como este ejemplo solamente utiliza métodos de Collection, cualquier objeto de una clase derivada de Collection debería funcionar, pero se ha cogido un ArrayList porque es el caballo de batalla de las colecciones y viene a tomar el relevo al Vector. El método add(), como su nombre sugiere, coloca un nuevo elemento en la colección. Sin embargo, la documentación indica claramente que add() "asegura que la colección contiene el elemento indicado". Esto es para que un Set tenga significado, ya que solamente añadirá el elemento si no se encuentra en la colección. Con un ArrayList, o cualquier otra lista ordenada, add() significa siempre "colocarlo dentro". Todas las colecciones pueden producir un Iterator invocando al método iterator(). Un Iterator viene a ser equivalente a una Enumeration, a la cual reemplaza, excepto en los siguientes puntos: 1. Utiliza un nombre que está históricamente aceptado y es conocido en toda la literatura de programación orientada a objetos 2. Utiliza nombres de métodos más cortos que la Enumeration: hasnext() en vez de hasmoreelements(), o next() en lugar de nextelement() 3. Añade un nuevo método, remove(), que permite eliminar el último elemento producido por el Iterator. Solamente se puede llamar a remove() una vez por cada llamada a next() En el ejemplo se utiliza un Iterator para desplazarse por la colección e ir imprimiendo cada uno de sus elementos. 124

125 A continuación se indican los métodos que están disponibles para las colecciones, es decir, lo que se puede hacer con un Set o una List, aunque las listas tengan funcionalidad añadida que ya se verá, y Map no hereda de Collection, así que se tratará aparte. boolean add( Object ) Asegura que la colección contiene el argumento. Devuelve false si no se puede añadir el argumento a la colección boolean addall( Collection ) Añade todos los elementos que se pasan en el argumento. Devuelve true si es capaz de incorporar a la colección cualquiera de los elementos del argumento void clear() Elimina todos los elementos que componen la colección boolean contains( Object ) Verdadero si la colección contiene el argumento que se pasa como parámetro boolean isempty() Verdadero si la colección está vacía, no contiene elemento alguno Iterator iterator() Devuelve un Iterator que se puede utilizar para desplazamientos a través de los elementos que componen la colección boolean remove( Object ) Si el argumento está en la colección, se elimina una instancia de ese elemento y se devuelve true si se ha conseguido boolean removeall( Collection ) Elimina todos los elementos que están contenidos en el argumento. Devuelve true si consigue eliminar cualquiera de ellos boolean retainall( Collection ) 125

126 Mantiene solamente los elementos que están contenidos en el argumento, es lo que sería una intersección en la teoría de conjuntos. Devuelve verdadero en caso de que se produzca algún cambio int size() Devuelve el número de elementos que componen la colección Object[] toarray() Devuelve un array conteniendo todos los elementos que forman parte de la colección. Este es un método opcional, lo cual significa que no está implementado para una Collection determinada. Si no puede devolver el array, lanzará una excepción de tipo UnsupportedOperationException El siguiente ejemplo, java421.java, muestra un ejemplo de todos estos métodos. De nuevo, recordar que esto funcionaría con cualquier cosa que derive de Collection, y que se utiliza un ArrayList para mantener un común denominador solamente. El primer método proporciona una forma se rellenar la colección con datos de prueba, en esta caso enteros convertidos a cadenas. El segundo método será utilizado con bastante frecuencia a partir de ahora. Las dos versiones de nuevacoleccion() crean ArrayList conteniendo diferente conjunto de datos que devuelven como objetos Collection, está claro que no se utiliza ningún otro interfaz diferente de Collection. El método print() también se usará a menudo a partir de ahora, y lo que hace es moverse a través de la Colección utilizando un Iterator, que cualquier Collection puede generar, y funciona con Listas, Conjuntos y Mapas. El método main() se usa simplemente para llamar a los métodos de la Colección. Listas Hay varias implementaciones de List, siendo ArrayList la que debería ser la elección por defecto, en caso de no tener que utilizar las características que proporcionan las demás implementaciones. List (interfaz) 126

127 Sets La ordenación es la característica más importante de una Lista, asegurando que los elementos siempre se mantendrán en una secuencia concreta. La Lista incorpora una serie de métodos a la Colección que permiten la inserción y borrar de elementos en medio de la Lista. Además, en la Lista Enlazada se puede generar un ListIterator para moverse a través de las lista en ambas direcciones. ArrayList Es una Lista volcada en un Array. Se debe utilizar en lugar de Vector como almacenamiento de objetos de propósito general. Permite un acceso aleatorio muy rápido a los elementos, pero realiza con bastante lentitud las operaciones de insertado y borrado de elementos en medio de la Lista. Se puede utilizar un ListIterator para moverse hacia atrás y hacia delante en la Lista, pero no para insertar y eliminar elementos. LinkedList Proporciona un óptimo acceso secuencial, permitiendo inserciones y borrado de elementos de en medio de la Lista muy rápidas. Sin embargo es bastante lento el acceso aleatorio, en comparación con la ArrayList. Dispone además de los métodos addlast(), getfirst(), getlast(), removefirst() y removelast(), que no están definidos en ningún interfaz o clase base y que permiten utilizar la Lista Enlazada como una Pila, una Cola o una Cola Doble. En el ejemplo java422.java, cubren gran parte de las acciones que se realizan en las Listas, como moverse con un Iterator, cambiar elementos, ver los efectos de la manipulación de la Lista y realizar operaciones sólo permitidas a las Listas Enlazadas. En testbasico() y moveriter() las llamadas se hacen simplemente para mostrar la sintaxis correcta, y aunque se recoge el valor devuelto, no se usa para nada. En otros casos, el valor devuelto no es capturado, porque no se utiliza normalmente. No obstante, el lector debe recurrir a la documentación de las clases para comprobar el uso de cualquier método antes de utilizarlo. 127

128 Set tiene exactamente el mismo interfaz que Collection, y no hay ninguna funcionalidad extra, como en el caso de las Listas. Un Set es exactamente una Colección, pero tiene utilizada en un entorno determinado, que es ideal para el uso de la herencia o el polimorfismo. Un Set sólo permite que exista una instancia de cada objeto. A continuación se muestran las diferentes implementaciones de Set, debiendo utilizarse HashSet en general, a no ser que se necesiten las características proporcionadas por alguna de las otras implementaciones. Set (interfaz) Cada elemento que se añada a un Set debe ser único, ya que el otro caso no se añadirá porque el Set no permite almacenar elementos duplicados. Los elementos incorporados al Conjunto deben tener definido el método equals(), en aras de establecer comparaciones para eliminar duplicados. Set tiene el mismo interfaz que Collection, y no garantiza el orden en que se encuentren almacenados los objetos que contenga. HashSet Es la elección más habitual, excepto en Sets que sean muy pequeños. Debe tener definido el método hashcode(). ArraySet Un Set encajonado en un Array. Esto es útil para Sets muy pequeños, especialmente aquellos que son creados y destruidos con frecuencia. Para estos pequeños Sets, la creación e iteración consume muchos menos recursos que en el caso del HashSet. Sin embargo, el rendimiento es muy malo en el caso de Sets con gran cantidad de elementos. TreeSet Es un Set ordenado, almacenado en un árbol balanceado. En este caso es muy fácil extraer una secuencia ordenada a partir de un Set de este tipo. 128

129 El ejemplo java423.java, no muestra todo lo que se puede hacer con un Set, sino que como Set es una Collection, y las posibilidades de las Colecciones ya se han visto, pues el ejemplo se limita a mostrar aquellas cosas que son particulares de los Sets. import java.util.*; public class java423 { public static void testvisual( Set a ) { java421.fill( a ); java421.fill( a ); java421.fill( a ); java421.print( a ); // No permite Duplicados! // Se añade otro Set al anterior a.addall( a ); a.add( "uno" ); a.add( "uno" ); a.add( "uno" ); java421.print( a ); // Buscamos ese elemento System.out.println( "a.contains(\"uno\"): "+a.contains( "uno" ) ); public static void main( String args[] ) { testvisual( new HashSet() ); testvisual( new ArraySet() ); Aunque se añaden valores duplicados al Set, a la hora de imprimirlos, se puede observar que solamente se acepta una instancia de cada valor. Cuando se ejecuta el ejemplo, se observa también que el orden que 129

130 Mapas mantiene el HashSet es diferente del que presenta el ArraySet, ya que cada uno tiene una forma de almacenar los elementos para la recuperación posterior. El ArraySet mantiene los elementos ordenados, mientras que el HashSet utiliza sus propias funciones para que las búsquedas sean muy rápidas. Cuando el lector cree sus propios tipos de estructuras de datos, deberá prestar atención porque un Set necesita alguna forma de poder mantener el orden de los elementos que lo integran, como se muestra en el ejemplo siguiente, java424.java. Las definiciones de los métodos equals() y hashcode() son semejantes a las de ejemplos anteriores. Se debe definir equals() en ambos casos, mientras que hashcode() solamente es necesario si la clase corresponde a un HashSet, que debería ser la primera elección a la hora de implementar un Set. Los Mapas almacenan información en base a parejas de valores, formados por una clave y el valor que corresponde a esa clave. Map (interfaz) Mantiene las asociaciones de pares clave-valor, de forma que se puede encontrar cualquier valor a partir de la clave correspondiente. HashMap Es una implementación basada en una tabla hash. Proporciona un rendimiento muy constante a la hora de insertar y localizar cualquier pareja de valores; aunque este rendimiento se puede ajustar a través de los constructores que permite fijar la capacidad y el factor de carga de la tabla hash. ArrayMap Es un Mapa circunscrito en un Array. Proporciona un control muy preciso sobre el orden de iteración. Está diseñado para su utilización con Mapas muy pequeños, especialmente con aquellos que se crean y destruyen muy 130

131 frecuentemente. En este caso de Mapas muy pequeños, la creación e iteración consume muy pocos recursos del sistema, y muchos menos que el HashMap. El rendimiento cae estrepitosamente cuando se intentan manejar Mapas grandes. TreeMap Es una implementación basada en un árbol balanceado. Cuando se observan las claves o los valores, se comprueba que están colocados en un orden concreto, determinado por Comparable o Comparator, que ya se verán. Lo importante de un TreeMap es que se pueden recuperar los elementos en un determinado orden. TreeMap es el único mapa que define el método submap(), que permite recuperar una parte del árbol solamente. El ejemplo java425.java contiene dos grupos de datos de prueba y un método rellena() que permite llenar cualquier mapa con cualquier array de dos dimensiones de Objects. Los métodos printclaves(), printvalores() y print() no son solamente unas cuantas utilidades, sino que demuestran como se pueden generar Colecciones que son vistas de un Mapa. El método keyset() genera un Set que contiene las claves que componen el Mapa; en este caso, es tratado como una Colección. Tratamiento similar se da a values(), que genera una List conteniendo todos los valores que se encuentran almacenados en el Mapa. Observar que las claves deben ser únicas, mientras que los valores pueden contener elementos duplicados. Debido a que las Colecciones son dependientes del Mapa, al representar solamente una vista concreta de parte de los datos del Mapa, cualquier cambio en una Colección se reflejará inmediatamente en el Mapa asociado. El método print() recoge el Iterator producido por entries() y lo utiliza para imprimir las parejas de elementos clave-valor. El resto del ejemplo proporciona ejemplos muy simples de cada una de las operaciones permitidas en un Mapa y prueba cada tipo de Mapa. 131

132 A la hora de crear Mapas propios, el lector debe tener en cuenta las mismas recomendaciones que anteriormente se proporcionaban en el caso de los Sets. CONECTANDOSE A BASE DE DATOS. JDBC Java Database Connectivity (JDBC) es una interfase de acceso a bases de datos estándar SQL que proporciona un acceso uniforme a una gran variedad de bases de datos relacionales. JDBC también proporciona una base común para la construcción de herramientas y utilidades de alto nivel. JDBC es un API de Java que permite al programador ejecutar instrucciones en lenguaje estándar de acceso a Bases de Datos, SQL (Structured Query Language, lenguaje estructurado de consultas), que es un lenguaje de muy alto nivel que permite crear, examinar, manipular y gestionar Bases de Datos relacionales. Para que una aplicación pueda hacer operaciones en una Base de Datos, ha de tener una conexión con ella, que se establece a través de un driver, que convierte el lenguaje de alto nivel a sentencias de Base de Datos. Es decir, las tres acciones principales que realizará JDBC son las de establecer la conexión a una base de datos, ya sea remota o no; enviar sentencias SQL a esa base de datos y, en tercer lugar, procesar los resultados obtenidos de la base de datos. El paquete JDK incluye JDBC a partir de la versión 1.1; El paquete java.sql que está incluido en la versión JDK 1.2 (conocido como el API JDBC 2.0) incluye muchas nuevas características no incluidas en el paquete java.sql que forma parte de la versión JDK 1.1 (referenciado como el API JDBC 1.0). Actualmente esta API se encuentra en la versión 3.0. Con el API JDBC 2.0, podremos hacer las siguientes cosas: 132

133 Ir hacia adelante o hacia atrás en una hoja de resultados o movernos a un fila específica. Hacer actualizaciones de las tablas de la base datos utilizando métodos Java en lugar de utilizar comandos SQL. Enviar múltiples secuencias SQL a la base de datos como una unidad, o batch. Utilizar los nuevos tipos de datos SQL3 como valores de columnas. DEFINICIÓN DE SQL El Lenguaje Estructurado de Consulta (SQL) es un conjunto especializado de órdenes de programación que permiten al programador (o usuario final) realizar las siguientes tareas: Recuperar datos de una o más tablas de una o mas bases de datos. Manipular datos de tablas insertando, eliminando o actualizando registros. Obtener información de resumen acerca de los datos de las tablas, como totales, recuento de registros y valores mínimos, máximos y medios. Crear, modificar o eliminar las tablas de una base de datos. Drivers JDBC Para usar JDBC con un sistema gestor de base de datos en particular, es necesario disponer del driver JDBC apropiado que haga de intermediario entre ésta y JDBC. JDBC es el API (Interfaz de Programación de la Aplicación) para la ejecución de sentencias SQL. Consiste en un conjunto de clases e interfases escritas en el lenguaje de programación Java. JDBC suministra un API estándar para los desarrolladores y hace posible escribir aplicaciones de base de datos usando un API puro Java. Usando JDBC es fácil enviar sentencias SQL virtualmente a cualquier sistema de base de datos. En otras palabras, con el API JDBC, no es necesario escribir un programa que acceda a una base de datos Sybase, otro para acceder a Oracle y otro para acceder a Informix. Un único programa escrito usando el API JDBC y el programa será capaz de enviar sentencias SQL a la base de 133

134 datos apropiada. Y, con una aplicación escrita en el lenguaje de programación Java, tampoco es necesario escribir diferentes aplicaciones para ejecutar en diferentes plataformas. La combinación de Java y JDBC permite al programador escribir una sola vez y ejecutarlo en cualquier entorno. Java, siendo robusto, seguro, fácil de usar, fácil de entender, y descargable automáticamente desde la red, es un lenguaje base excelente para aplicaciones de base de datos. JDBC expande las posibilidades de Java. Por ejemplo, con Java y JDBC API, es posible publicar una página web que contenga un applet que usa información obtenida de una base de datos remota. O una empresa puede usar JDBC para conectar a todos sus empleados (incluso si usan un conglomerado de máquinas Windows, Macintosh y UNIX) a una base de datos interna vía intranet. Con cada vez más y más programadores desarrollando en lenguaje Java, la necesidad de acceso fácil a base de datos desde Java continúa creciendo. Qué hace JDBC? Simplemente JDBC hace posible estas tres cosas: Establece una conexión con la base de datos. Envía sentencias SQL Procesa los resultados. El acceso a base de datos es siempre un punto a considerar por nuestras aplicaciones. Para esto en Java usamos Java Database Connectivity conocido por la abreviación JDBC. Cuando instalamos el JDK (Java Development Kit) automáticamente se instala esta API (JDBC) y con ella en forma muy sencilla podemos hacer consultas, mantenimientos y todo tipo de transacciones a una base de datos. Para la gente del mundo Windows, JDBC es para Java lo que ODBC es para Windows. Windows en general no sabe nada acerca de las bases de datos, pero define el estándar ODBC consistente en un conjunto de primitivas que cualquier driver o fuente ODBC debe ser capaz de entender y manipular. Los 134

135 programadores que a su vez deseen escribir programas para manejar bases de datos genéricas en Windows utilizan las llamadas ODBC. Con JDBC ocurre exactamente lo mismo: JDBC es una especificación de un conjunto de clases y métodos de operación que permiten a cualquier programa Java acceder a sistemas de bases de datos de forma homogénea. Lógicamente, al igual que ODBC, la aplicación de Java debe tener acceso a un driver JDBC adecuado. Este driver es el que implementa la funcionalidad de todas las clases de acceso a datos y proporciona la comunicación entre el API JDBC y la base de datos real. La necesidad de JDBC, a pesar de la existencia de ODBC, viene dada porque ODBC es un interfaz escrito en lenguaje C, que al no ser un lenguaje portable, haría que las aplicaciones Java también perdiesen la portabilidad. Y además, ODBC tiene el inconveniente de que se ha de instalar manualmente en cada máquina; al contrario que los drivers JDBC, que al estar escritos en Java son automáticamente instalables, portables y seguros. Toda la conectividad de bases de datos de Java se basa en sentencias SQL, por lo que se hace imprescindible un conocimiento adecuado de SQL para realizar cualquier clase de operación de bases de datos. Aunque, afortunadamente, casi 135

136 todos los entornos de desarrollo Java ofrecen componentes visuales que proporcionan una funcionalidad suficientemente potente sin necesidad de que sea necesario utilizar SQL, aunque para usar directamente el JDK se haga imprescindible. La especificación JDBC requiere que cualquier driver JDBC sea compatible con al menos el nivel «de entrada» de ANSI SQL 92 (ANSI SQL 92 Entry Level). ACCESO A BASE DE DATOS CON JDBC El API JDBC soporta dos modelos diferentes de acceso a Bases de Datos, los modelos de dos y tres capas. Modelo de dos capas Este modelo se basa en que la conexión entre la aplicación Java o el applet que se ejecuta en el navegador, se conectan directamente a la base de datos. Esto significa que el driver JDBC específico para conectarse con la base de datos, debe residir en el sistema local. La base de datos puede estar en cualquier otra máquina y se accede a ella mediante la red. Esta es la configuración de típica Cliente/Servidor: el programa cliente envía instrucciones SQL a la base de datos, ésta las procesa y envía los resultados de vuelta a la aplicación. Modelo de tres capas 136

137 En este modelo de acceso a las bases de datos, las instrucciones son enviadas a una capa intermedia entre Cliente y Servidor, que es la que se encarga de enviar las sentencias SQL a la base de datos y recoger el resultado desde la base de datos. En este caso el usuario no tiene contacto directo, ni a través de la red, con la máquina donde reside la base de datos. Este modelo presenta la ventaja de que el nivel intermedio mantiene en todo momento el control del tipo de operaciones que se realizan contra la base de datos, y además, está la ventaja adicional de que los drivers JDBC no tienen que residir en la máquina cliente, lo cual libera al usuario de la instalación de cualquier tipo de driver. Tipos de drivers Un driver JDBC puede pertenecer a una de cuatro categorías diferentes en cuanto a la forma de operar, entonces tenemos que considerar que existen 4 formas de usar JDBC para conexión con base de datos: El puente JDBC-ODBC Driver de Java parcialmente nativo Driver JDBC de Java puro Driver de protocolo de Java puro 137

138 El puente JDBC-ODBC Esta forma es la más sencilla y es la que usaremos inicialmente para comunicarnos con el gestor SQL Server. Para esto necesitamos del ODBC (Open Database Connectivity) de Microsoft, a través del cual crearemos un DSN (Data Source Name) que nos permitirá crear una cadena de conexión de información sobre la base de datos. El ODBC esta hecho en lenguaje C, mientras que JDBC en Java. El ODBC se comunica con la base de datos y el JDBC con el ODBC. La primera categoría de drivers es la utilizada por Sun inicialmente para popularizar JDBC y consiste en aprovechar todo lo existente, estableciendo un puente entre JDBC y ODBC. Este driver convierte todas las llamadas JDBC a llamadas ODBC y realiza la conversión correspondiente de los resultados. La ventaja de este driver, que se proporciona con el JDK, es que Java dispone de acceso inmediato a todas las fuentes posibles de bases de datos y no hay que hacer ninguna configuración adicional aparte de la ya existente. No obstante, tiene dos desventajas muy importantes; por un lado, la mayoría de los drivers ODBC a su vez convierten sus llamadas a llamadas a una librería nativa del fabricante DBMS, con lo cual la lentitud del driver JDBC- ODBC puede ser exasperante, al llevar dos capas adicionales que no añaden funcionalidad alguna; y por otra parte, el puente JDBC-ODBC requiere una instalación ODBC ya existente y configurada. 138

139 Lo anterior implica que para distribuir con seguridad una aplicación Java que use JDBC habría que limitarse en primer lugar a entornos Windows (donde está definido ODBC) y en segundo lugar, proporcionar los drivers ODBC adecuados y configurarlos correctamente. Esto hace que este tipo de drivers esté totalmente descartado en el caso de aplicaciones comerciales, e incluso en cualquier otro desarrollo, debe ser considerado como una solución transitoria, porque el desarrollo de drivers totalmente en Java hará innecesario el uso de estos puentes. Java/Binario (Driver de Java parcialmente nativo) Esta forma está integrada de controladores que se comunican con el servidor de base de datos en el protocolo nativo del servidor. Por ejemplo para el gestor DB2 necesitaríamos un driver nativo de DB2 de IBM, Para Informix necesitaríamos un driver nativo de Informix de Unix. Nuestro JDBC, hecho en Java se comunicaría con estos drivers. Este driver se salta la capa ODBC y habla directamente con la librería nativa del fabricante del sistema DBMS (como pudiera ser DB-Library para Microsoft SQL Server o CT-Lib para Sybase SQL Server). Este driver es un driver 100% Java pero aún así necesita la existencia de un código binario (la librería DBMS) en la máquina del cliente, con las limitaciones y problemas que esto implica. Driver JDBC-Net de Java puro (100% Java/Protocolo nativo) En esta forma los drivers están hechos en Java puro, pero sin embargo utilizan protocolos estándares, como por ejemplo HTTP, con servidor de base 139

140 de datos. El servidor traduce el protocolo de red. Para el caso de Windows, puede usar ODBC. Es un driver realizado completamente en Java que se comunica con el servidor DBMS utilizando el protocolo de red nativo del servidor. De esta forma, el driver no necesita intermediarios para hablar con el servidor y convierte todas las peticiones JDBC en peticiones de red contra el servidor. La ventaja de este tipo de driver es que es una solución 100% Java y, por lo tanto, independiente de la máquina en la que se va a ejecutar el programa. Igualmente, dependiendo de la forma en que esté programado el driver, puede no necesitar ninguna clase de configuración por parte del usuario. La única desventaja de este tipo de drivers es que el cliente está ligado a un servidor DBMS concreto, ya que el protocolo de red que utiliza MS SQL Server por ejemplo no tiene nada que ver con el utilizado por DB2, PostGres u Oracle. La mayoría de los fabricantes de bases de datos han incorporado a sus propios drivers JDBC del segundo o tercer tipo, con la ventaja de que no suponen un coste adicional. Driver de protocolo de Java puro (100% Java/Protocolo independiente) En esta última forma, conformada por drivers de java puro, la comunicación es a través de un protocolo específico para la marca de base de datos que se usa. Este tipo de conexión es más eficiente que usar ODBC, pero que requiere un costo monetario en la compra de estos tipos de drivers. 140

141 Esta es la opción más flexible, se trata de un driver 100% Java / Protocolo independiente, que requiere la presencia de un intermediario en el servidor. En este caso, el driver JDBC hace las peticiones de datos al intermediario en un protocolo de red independiente del servidor DBMS. El intermediario a su vez, que está ubicado en el lado del servidor, convierte las peticiones JDBC en peticiones nativas del sistema DBMS. La ventaja de este método es inmediata: el programa que se ejecuta en el cliente, y aparte de las ventajas de los drivers 100% Java, también presenta la independencia respecto al sistema de bases de datos que se encuentra en el servidor. De esta forma, si una empresa distribuye una aplicación Java para que sus usuarios puedan acceder a su servidor MS SQL y posteriormente decide cambiar el servidor por Oracle, PostGres o DB2, no necesita volver a distribuir la aplicación, sino que únicamente debe reconfigurar la aplicación residente en el servidor que se encarga de transformar las peticiones de red en peticiones nativas. La única desventaja de este tipo de drivers es que la aplicación intermediaria es una aplicación independiente que suele tener un coste adicional por servidor físico, que hay que añadir al coste del servidor de bases de datos. Aproximación a JDBC JDBC define ocho interfaces para operaciones con bases de datos, de las que se derivan las clases correspondientes. La figura siguiente, en formato OMT, con nomenclatura UML, muestra la interrelación entre estas clases según el modelo de objetos de la especificación de JDBC. 141

142 La clase que se encarga de cargar inicialmente todos los drivers JDBC disponibles es DriverManager. Una aplicación puede utilizar DriverManager para obtener un objeto de tipo conexión, Connection, con una base de datos. La conexión se especifica siguiendo una sintaxis basada en la especificación más amplia de los URL, de la forma jdbc:subprotocolo//servidor:puerto/base de datos Por ejemplo, si se utiliza msql el nombre del subprotocolo será msql. En algunas ocasiones es necesario identificar aún más el protocolo. Por ejemplo, si se usa el puente JDBC-ODBC no es suficiente con jdbc:odbc, ya que pueden existir múltiples drivers ODBC, y en este caso, hay que especificar aún más, mediante jdbc:odbc:fuente de datos. Una vez que se tiene un objeto de tipo Connection, se pueden crear sentencias, statements, ejecutables. Cada una de estas sentencias puede devolver cero o más resultados, que se devuelven como objetos de tipo ResultSet. 142

143 Y la tabla siguiente muestra la misma lista de clases e interfaces junto con una breve descripción. Clase/Interface Driver DriverManager DriverPropertyInfo Connection DatabaseMetadata Statement PreparedStatement CallableStatement ResultSet Descripción Permite conectarse a una base de datos: cada gestor de base de datos requiere un driver distinto Permite gestionar todos los drivers instalados en el sistema Proporciona diversa información acerca de un driver Representa una conexión con una base de datos. Una aplicación puede tener más de una conexión a más de una base de datos Proporciona información acerca de una Base de Datos, como las tablas que contiene, etc. Permite ejecutar sentencias SQL sin parámetros Permite ejecutar sentencias SQL con parámetros de entrada/td> Permite ejecutar sentencias SQL con parámetros de entrada y salida, típicamente procedimientos almacenados Contiene las filas o registros obtenidos al ejecutar un SELECT ResultSetMetadata Permite obtener información sobre un ResultSet, como el número de columnas, sus nombres, etc. La primera aplicación que se va a crear simplemente crea una tabla en el servidor, utilizando para ello el puente JDBC-ODBC, siendo la fuente de datos un servidor SQL Server. Si el lector desea utilizar otra fuente ODBC, no tiene más que cambiar los parámetros de getconnection() en el código fuente. El establecimiento de la conexión es, como se puede es fácil suponer, la parte que mayores problemas puede dar en una aplicación de este tipo. Si algo no funciona, cosa más que probable en los primeros intentos, es muy recomendable activar la traza de llamadas ODBC desde el panel de control. De esta forma se puede ver lo que está haciendo exactamente el driver JDBC y por qué motivo no se está estableciendo la conexión. El siguiente diagrama relaciona las cuatro clases principales que va a usar cualquier programa Java con JDBC, y representa el esqueleto de cualquiera de los programas que se desarrollan para atacar a bases de datos. 143

144 La aplicación siguiente es un ejemplo en donde se aplica el esquema anterior, se trata de instalación java2101.java, crea una tabla y rellena algunos datos iniciales. import java.sql.*; class java2101 { static public void main( String[] args ) { Connection conexion; Statement sentencia; ResultSet resultado; System.out.println( "Iniciando programa." ); // Se carga el driver JDBC-ODBC try { Class.forName( "sun.jdbc.odbc.jdbcodbcdriver" ); catch( Exception e ) { System.out.println( "No se pudo cargar el puente JDBC-ODBC." ); return; try { 144

145 // Se establece la conexión con la base de datos conexion = DriverManager.getConnection( "jdbc:odbc:tutorial","","" ); sentencia = conexion.createstatement(); try { // Se elimina la tabla en caso de que ya existiese sentencia.execute( "DROP TABLE AGENDA" ); catch( SQLException e ) {; // Esto es código SQL sentencia.execute( "CREATE TABLE AMIGOS ("+ " NOMBRE VARCHAR(15) NOT NULL, " + " APELLIDOS VARCHAR(30) NOT NULL, " + " CUMPLE DATETIME) " ); sentencia.execute( "INSERT INTO AMIGOS " + "VALUES('JOSE','GONZALEZ','03/15/1973')" ); sentencia.execute( "INSERT INTO AMIGOS " + "VALUES('PEDRO','GOMEZ','08/15/1961')" ); sentencia.execute( "INSERT INTO AMIGOS " + "VALUES('GONZALO','PEREZ', NULL)" ); catch( Exception e ) { System.out.println( e ); return; System.out.println( "Creacion finalizada." ); Las partes más interesantes del código son las que se van a revisar a continuación, profundizando en cada uno de los pasos. Lo primero que se hace es importar toda la funcionalidad de JDBC, a través de la primera sentencia ejecutable del programa. import java.sql.*; Las siguientes líneas son las que cargan el puente JDBC-ODBC, mediante el método forname() de la clase Class. try { Class.forName( "sun.jdbc.odbc.jdbcodbcdriver" ); catch( Exception e ) { System.out.println( "No se pudo cargar el puente JDBC-ODBC." ); return; 145

146 En teoría esto no es necesario, ya que DriverManager se encarga de leer todos los drivers JDBC compatibles, pero no siempre ocurre así, por lo que es mejor asegurarse. El método forname() localiza, lee y enlaza dinámicamente una clase determinada. Para drivers JDBC, la sintaxis que JavaSoft recomienda de forname() es nombreempresa.nombrebasedatos.nombredriver, y el driver deberá estar ubicado en el directorio nombreempresa\nombrebasedatos\nombredriver.class a partir del directorio indicado por la variable de entorno CLASSPATH. En este caso se indica que el puente JDBC-ODBC que se desea leer es precisamente el de Sun. Si por cualquier motivo no es posible conseguir cargar JdbcOdbcDriver.class, se intercepta la excepción y se sale del programa. En este momento es la hora de echar mano de la información que puedan proporcionar las trazas ODBC. La carga del driver también se puede especificar desde la línea de comandos al lanzar la aplicación: java -Djdbc.drivers=sun.jdbc.odbc.JdbcOdbcDriver Exprograma A continuación, se solicita a DriverManager que proporcione una conexión para una fuente de datos ODBC. El parámetro jdbc:odbc:tutorial especifica que la intención es acceder a la fuente de datos con nombre Tutorial, Data Source Name o DSN, en la terminología ODBC. conexion = DriverManager.getConnection("jdbc:odbc:Tutorial","","" ); El segundo y tercer parámetro son el nombre del usuario y la clave con la cual se intentará la conexión. En este caso el acceso es libre, para acceder como administrador del sistema en el caso de un servidor MS SQL se usa la cuenta sa o system administrator, cuya cuenta de acceso no tiene clave definida; en caso de acceder a un servidor MS Access, la cuenta del administrador es admin y también sin clave definida. Esta es la única línea que con seguridad habrá de cambiar el programador para probar sus aplicaciones. getconnection admite también una forma con un único parámetro (el URL de la base de datos), que debe proporcionar toda la información de conexión necesaria al driver JDBC 146

147 correspondiente. Para el caso JDBC-ODBC, se puede utilizar la sentencia equivalente: DriverManager.getConnection ( "jdbc:odbc:sql;uid=sa;pwd=" ); Para el resto de los drivers JDBC, habrá que consultar la documentación de cada driver en concreto. Inmediatamente después de obtener la conexión, en la siguiente línea sentencia = conexion.createstatement(); se solicita que proporcione un objeto de tipo Statement para poder ejecutar sentencias a través de esa conexión. Para ello se dispone de los métodos execute(string sentencia) para ejecutar una petición SQL que no devuelve datos o executequery(string sentencia) para ejecutar una consulta SQL. Este último método devuelve un objeto de tipo ResultSet. Una vez que se tiene el objeto Statement ya se pueden lanzar consultas y ejecutar sentencias contra el servidor. A partir de aquí el resto del programa realmente es SQL «adornado»: en la línea: sentencia.execute( "DROP TABLE AMIGOS" ); se ejecuta DROP TABLE AMIGOS para borrar cualquier tabla existente anteriormente. Puesto que este ejemplo es una aplicación «de instalación» y es posible que la tabla AMIGOS no exista, dando como resultado una excepción, se aísla la sentencia.execute() mediante un try y un catch. La línea siguiente ejecuta una sentencia SQL que crea la tabla AMIGOS con tres campos: NOMBRE, APELLIDOS y CUMPLE. De ellos, únicamente el tercero, correspondiente al cumpleaños, es el que puede ser desconocido, es decir, puede contener valores nulos. sentencia.execute( "CREATE TABLE AMIGOS ("+ " NOMBRE VARCHAR(15) NOT NULL, " + " APELLIDOS VARCHAR(30) NOT NULL, " + " CUMPLE DATETIME) " ); 147

148 Y ya en las líneas siguientes se ejecutan sentencias INSERT para rellenar con datos la tabla. En todo momento se ha colocado un try... catch exterior para interceptar cualquier excepción que puedan dar las sentencias. En general, para java.sql está definida una clase especial de excepciones que es SQLException. Se obtendrá una excepción de este tipo cuando ocurra cualquier error de proceso de JDBC, tanto si es a nivel JDBC como si es a nivel inferior (ODBC o de protocolo). Por ejemplo, si en lugar de GONZALO en la línea correspondiente a la última inserción en la Base de Datos, se intenta añadir un nombre nulo (NULL), se generará una excepción SQLException con el mensaje [Microsoft][ODBC SQL Server Driver][SQL Server]Attempt to insert the value NULL into column 'NOMBRE', table 'master.dbo.agenda'; column does not allow nulls. INSERT fails. que en el caso de Microsoft Access sería: [Microsoft][ODBC Microsoft Access 97 Driver] The field 'AGENDA.NOMBRE' can't contain a Null value because the Required property for this field is set to True. Enter a value in this field. En román paladino, el hecho de que la columna NOMBRE esté definida como NOT NULL, hace que no pueda quedarse vacía. Ahora se verán los pasos que hay que dar para obtener información a partir de una base de datos ya creada. Como se ha dicho anteriormente, se utilizará executequery en lugar de execute para obtener resultados. Se sustituyen las líneas que contenían esa sentencia por: resultado = sentencia.executequery( "SELECT * FROM AMIGOS" ); while( resultado.next() ) { String nombre = resultado.getstring( "NOMBRE" ); String apellidos = resultado.getstring( "APELLIDOS" ); String cumple = resultado.getstring( "CUMPLE" ); System.out.println( "El aniversario de D. " + nombre + " " + apellidos + ", se celebra el " + cumple ); 148

149 En este caso, en la primera línea se utiliza executequery para obtener el resultado de SELECT * FROM AMIGOS. Mediante resultado.next() la posición se situará en el «siguiente» elemento del resultado, o bien sobre el primero si todavía no se ha utilizado. La función next() devuelve true o false si el elemento existe, de forma que se puede iterar mediante while ( resultado.next() ) para tener acceso a todos los elementos. A continuación, en las líneas siguientes se utilizan los métodos getxxx() de resultado para tener acceso a las diferentes columnas. El acceso se puede hacer por el nombre de la columna, como en las dos primeras líneas, o bien mediante su ubicación relativa, como en la última línea. Además de getstring() están disponibles getboolean(), getbyte(), getdouble(), getfloat(), getint(), getlong(), getnumeric(), getobject(), getshort(), getdate(), gettime() y getunicodestream(), cada uno de los cuales devuelve la columna en el formato correspondiente, si es posible. Después de haber trabajado con una sentencia o una conexión es recomendable cerrarla mediante sentencia.close() o conexión.close(). De forma predeterminada los drivers JDBC deben hacer un COMMIT de cada sentencia. Este comportamiento se puede modificar mediante el método Connection.setAutoCommit( boolean nuevovalor). En el caso de que se establezca AutoCommit a false, será necesario llamar de forma explícita a Connection.commit() para guardar los cambios realizados o Connection.rollback() para deshacerlos. Como el lector habrá podido comprobar hasta ahora, no hay nada intrínsecamente difícil en conectar Java con una base de datos remota. Los posibles problemas de conexión que puede haber (selección del driver o fuente de datos adecuada, obtención de acceso, etc.), son problemas que se tendrían de una u otra forma en cualquier lenguaje de programación. El objeto ResultSet devuelto por el método executequery(), permite recorrer las filas obtenidas, no proporciona información referente a la estructura de cada una de ellas; para ello se utiliza ResultSetMetaData, que permite obtener el tipo de 149

150 cada campo o columna, su nombre, si es del tipo autoincremento, si es sensible a mayúsculas, si se puede escribir en dicha columna, si admite valores nulos, etc. Para obtener un objeto de tipo ResultSetMetaData basta con llamar al método getmetadata() del objeto ResultSet. En la lista siguiente aparecen algunos de los métodos más importantes de ResultSetMetaData, que permiten averiguar toda la información necesaria para formatear la información correspondiente a una columna, etc. getcatalogname() Nombre de la columna en el catálogo de la base de datos getcolumnname() Nombre de la columna getcolumnlabel() Nombre a utilizar a la hora de imprimir el nombre de la columna getcolumndisplaysize() Ancho máximo en caracteres necesario para mostrar el contenido de la columna getcolumncount() Número de columnas en el ResultSet gettablename() Nombre de la tabla a que pertenece la columna getprecision() Número de dígitos de la columna getscale() Número de decimales para la columna getcolumntype() Tipo de la columna (uno de los tipos SQL en java.sql.types) getcolumntypename() Nombre del tipo de la columna issigned() Para números, indica si la columna corresponde a un número con signo isautoincrement() Indica si la columna es de tipo autoincremento 150

151 iscurrency() Indica si la columna contiene un valor monetario iscasesensitive() Indica si la columna contiene un texto sensible a mayúsculas isnullable() Indica si la columna puede contener un NULL SQL. Puede devolver los valores columnnonulls, columnnullable o columnnullableunknown, miembros finales estáticos de ResultSetMetaData (constantes) isreadonly() Indica si la columna es de solo lectura iswritable() Indica si la columna puede modificarse, aunque no lo garantiza isdefinitivelywritable() Indica si es absolutamente seguro que la columna se puede modificar issearchable() Indica si es posible utilizar la columna para determinar los criterios de búsqueda de un SELECT getschemaname() Devuelve el texto correspondiente al esquema de la base de datos para esa columna En general pues, los objetos que se van a poder encontrar en una aplicación que utilice JDBC, serán los que se indican a continuación. Connection Representa la conexión con la base de datos. Es el objeto que permite realizar las consultas SQL y obtener los resultados de dichas consultas. Es el objeto base para la creación de los objetos de acceso a la base de datos. DriverManager Encargado de mantener los drivers que están disponibles en una aplicación concreta. Es el objeto que mantiene las funciones de 151

152 administración de las operaciones que se realizan con la base de datos. Statement Se utiliza para enviar las sentencias SQL simples, aquellas que no necesitan parámetros, a la base de datos. PreparedStatement Tiene una relación de herencia con el objeto Statement, añadiéndole la funcionalidad de poder utilizar parámetros de entrada. Además, tiene la particularidad de que la pregunta ya ha sido compilada antes de ser realizada, por lo que se denomina preparada. La principal ventaja, aparte de la utilización de parámetros, es la rapidez de ejecución de la pregunta. CallableStatement ResultSet Transacciones Tiene una relación de herencia cn el objeto PreparedStatement. Permite utilizar funciones implementadas directamente sobre el sistema de gestión de la base de datos. Teniendo en cuenta que éste posee información adicional sobre el uso de las estructuras internas, índices, etc.; las funciones se realizarán de forma más eficiente. Este tipo de operaciones es muy utilizada en el caso de ser funciones muy complicadas o bien que vayan a ser ejecutadas varias veces a lo largo del tiempo de vida de la aplicación. Contiene la tabla resultado de la pregunta SQL que se haya realizado. En párrafos anteriores se han comentado los métodos que proporciona este objeto para recorrer dicha tabla. En párrafos anteriores se ha tratado de la creación y uso de sentencias SQL, que siempre se obtenían llamando a un método de un objeto de tipo Connection, como createstatement() o preparestatement(). El uso de transacciones, también se controla mediante métodos del objeto Connection. Como ya se ha dicho, Connection representa una conexión a una Base de datos dada, luego 152

153 representa el lugar adecuado para el manejo de transacciones, dado que estas afectan a todas las sentencias ejecutadas sobre una conexión a la base de datos. Por defecto, una conexión funciona en modo autocommit, es decir, cada vez que se ejecuta una sentencia SQL se abre y se cierra automáticamente una transacción, que sólo afecta a dicha sentencia. Es posible modificar esta opción mediante setautocommit(), mientras que getautocommit() indica si se está en modo autocommit o no. Si no se está trabajando en modo autocommit será necesario que se cierren explícitamente las transacciones mediante commit() si tienen éxito, o rollback(), si fallan; nótese que, tras cerrar una transacción, la próxima vez que se ejecute una sentencia SQL se abrirá automáticamente una nueva, por lo que no existe ningún método del tipo que permita iniciar una transacción. Es posible también especificar el nivel de aislamiento de una transacción, mediante settransactionisolation(), así como averiguar cuál es el nivel de aislamiento de la actual mediante gettransactionisolation(). Los niveles de aislamiento se representan mediante las constantes que se muestran en la lista siguiente, en la cual se explica muy básicamente el efecto de cada nivel de aislamiento. TRANSACTION_NONE No se pueden utilizar transacciones. TRANSACTION_READ_UNCOMMITTED Desde esta transacción se pueden llegar a ver registros que han sido modificados por otra transacción, pero no guardados, por lo que podemos llegar a trabajar con valores que nunca llegan a guardarse realmente. TRANSACTION_READ_COMMITTED Se ven solo las modificaciones ya guardadas hechas por otras transacciones. TRANSACTION_REPEATABLE_READ Si se leyó un registro, y otra transacción lo modifica, guardándolo, y lo volvemos a leer, seguiremos viendo la información que había cuando lo 153

154 leímos por primera vez. Esto proporciona un nivel de consistencia mayor que los niveles de aislamiento anteriores. TRANSACTION_SERIALIZABLE Se verán todos los registros tal y como estaban antes de comenzar la transacción, no importa las modificaciones que otras transacciones hagan, ni que lo hayamos leído antes o no. Si se añadió algún nuevo registro, tampoco se verá. Además de manejar transacciones, el objeto Connection también proporciona algunos otros métodos que permiten especificar características de una conexión a una base de datos; por ejemplo, los métodos isreadonly() y setreadonly() permiten averiguar si una conexión a una base de datos es de sólo lectura, o hacerla de sólo lectura. El método isclosed() permite averiguar si una conexión está cerrada o no, y nativesql() permite obtener la cadena SQL que el driver mandaría a la base de datos si se tratase de ejecutar la cadena SQL especificada, permitiendo averiguar qué es exactamente lo que se le envía a la base de datos. Información de la Base de Datos Falta aún una pieza importante a la hora de trabajar con la conexión a la base de datos mediante Connection, y es la posibilidad de poder interrogar sobre las características de una base de datos; por ejemplo, puede se interesante saber si la base de datos soporta cierto nivel de aislamiento en una transacción, como la TRANSACTION_SERIALIZABLE, que muchos gestores no soportan. Para esto está otro de los interfaces que proporciona JDBC, DatabaseMetaData, al que es posible interrogar sobre las características de la base de datos con la que se está trabajando. Es posible obtener un objeto de tipo DatabaseMetaData mediante el método getmetadata() de Connection. DatabaseMetaData proporciona diversa información sobre una base de datos, y cuenta con varias docenas de métodos, a través de los cuales es posible obtener gran cantidad de información acerca de una tabla; por ejemplo, getcolumns() devuelve las columnas de una tabla, getprimarykeys() devuelve la lista de columnas que forman la clave 154

155 primaria, getindexinfo() devuelve información acerca de sus índices, mientras que getexportedkeys() devuelve la lista de todas las claves ajenas que utilizan la clave primaria de esta tabla, y getimportedkeys() las claves ajenas existentes en la tabla. El método gettables() devuelve la lista de todas las tablas en la base de datos, mientras que getprocedures() devuelve la lista de procedimientos almacenados. Muchos de los métodos de DatabaseMetaData devuelven un objeto de tipo ResultSet que contiene la información deseada. El listado que se presenta a continuación, muestra el código necesario para obtener todas las tablas de una base de datos. String nombretablas = "%"; // Listamos todas las tablas String tipos[] = new String[1]; // Listamos sólo tablas tipos[0] = "TABLE"; DatabaseMetaData dbmd = conexion.getmetadata(); ResultSet tablas = dbmd.gettables( null,null,nombretablas,tipos ); boolean seguir = tablas.next(); while( seguir ) { // Mostramos sólo el nombre de las tablas, guardado // en la columna "TABLE_NAME" System.out.println( ; tablas.getstring( tablas.findcolumn( "TABLE_NAME" ) ) ); seguir = tablas.next(); Hay todo un grupo de métodos que permiten averiguar si ciertas características están soportadas por la base de datos; entre ellos, destacan supportsgroupby() indica si se soporta el uso de GROUP BY en un SELECT, mientras que supportsouterjoins() indica si se pueden llevar a cabo outer-joins. El método supportstransactions(), comentado antes, indica si cierto tipo de transacciones está soportado o no. Otros métodos de utilidad son getusername(), que devuelve el nombre del usuario actual; geturl(), que devuelve el URL de la base de datos actual. DatabaseMetaData proporciona muchos otros métodos que permiten averiguar cosas tales como el máximo número de columnas utilizable en 155

156 un SELECT, etc. En general, casi cualquier pregunta sobre las capacidades de la base de datos se puede contestar llamando a los distintos métodos del objeto DatabaseMetaData, que merece la pena que el lector consulte cuando no sepa si cierta característica está soportada. Puente Jdbc-Odbc Para desarrollar nuestras aplicaciones nosotros usaremos la primera forma de conexión a base de datos con el puente JDBC-ODBC, que es la más sencilla y libre de costos monetarios. Siempre debemos considerar la siguiente figura en el desarrollo completo de nuestra aplicación: Lo primero que tenemos considerar es el tener nuestra base de datos en SQL Server. Luego construir el DSN (Data Source Name) mediante ODBC. Considerar que los objetos para acceder a base de datos se encuentran en la API JDBC, por lo tanto una línea obligatoria en nuestro programa en Java es: impor java.sql.*; // Acceso a los objetos Connection, Statement y ResulSet Finalmente podemos centrarnos en desarrollar el código Java que complete nuestra aplicación. Acceso A Una Base De Datos Con Java 156

157 La siguiente figura muestra un. Esta aplicación tiene efecto si hemos creado el DSN dsnpubs. Al dar clic en el botón Probar DSN veremos el siguiente resultado: El código para este programa esta dado por 2 clases: Formulario y MiPanel. El código de la clase Formulario es el siguiente: //Archivo Formulario import javax.swing.*; import java.awt.*; import java.awt.event.*; class Formulario extends JFrame { static int wf= 400, hf= 300; //"static" xq se van a usar en "main()" public Formulario(String s){ super(s); //invoca al padre y le pasa la cadena "s" como título getcontentpane().add(new MiPanel()); //crea el panel en el formulario setlocation((gettoolkit().getscreensize().width - wf)/2, (gettoolkit().getscreensize().height - hf)/2); //para ubicar el formulario en una posicion especifica 157

158 // de la pantalla //gettoolkit() me da informción útil, getscreensize() // dimensiones de la pantalla (width, height) static public void main(string[] arg) { JFrame f= new Formulario("Carlos Durand"); //para cerrar la ventana cuando se da click a la "X" //de la ventana f.addwindowlistener(new WindowAdapter() { public void windowclosing(windowevent e) { System.exit(0); ); f.setsize(wf, hf); f.setvisible(true); El código de MiPanel es el siguiente: //Archivo MiPanel import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.sql.*; // Acceso a objetos de JDBC class MiPanel extends JPanel implements ActionListener { JButton b= new JButton("Probar DSN"); JTextArea t= new JTextArea(); public MiPanel() { setlayout(new BorderLayout()); b.addactionlistener(this); add(b, BorderLayout.NORTH); 158

159 Explicación: add(t, BorderLayout.CENTER); // Para eventos public void actionperformed(actionevent e) { try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection cn= DriverManager.getConnection( "jdbc:odbc:dsnpubs", "sa", ""); DatabaseMetaData meta= cn.getmetadata(); t.settext("exito en conexión...!\n"); t.append("\ndatabase:\t" + meta.getdatabaseproductname()); t.append("\nversion:\t" + meta.getdatabaseproductversion()); cn.close(); catch(exception ex) { t.settext("la conexión fracasó por:\n\n"); t.append(ex.tostring()); Los objetos de JDBC deben estar siempre dentro de una instrucción try - catch Para indicar que tipo de driver vamos a usar en nuestra aplicación ponemos la sentencia: Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Por la anterior sentencia el driver a usar es el puente JDBC-ODBC. El administrador de drivers (DriverManager) del JDBC para el caso del puente JDBCODBC nos pide 3 argumentos: el DSN, login y password, como se indica en la siguiente sentencia: Connection cn= DriverManager.getConnection("jdbc:odbc:dsnPubs", "sa", ""); 159

160 Este nos devuelve un objeto de tipo Connection con el cual se apertura el acceso a la base de datos. Existen objetos para la metadata. La metadata es la data del entorno de los datos, por ejemplo si una columna tiene la data Juan Pérez, entonces su metadata es el nombre de la columna por ejemplo Nombre. Para recoger metadata del gestor de base de datos usamos un objeto de la clase DatabaseMetaData como indica la siguiente sentencia: DatabaseMetaData meta= cn.getmetadata(); La metadata de la base de datos es pedida a través de un objeto de la clase Connection (cn). El objeto meta de la clase DatabaseMetaData nos permite obtener el nombre y la versión del gestor de base de datos, como muestran las dos sentencias siguientes: t.append("\ndatabase:\t" + meta.getdatabaseproductname()); t.append("\nversion:\t" + meta.getdatabaseproductversion()); Podemos manipular excepciones a través de un objeto de la clase Exception o de la clase SQLException. En nuestra aplicación lo hicimos de la siguiente forma: catch(exception ex) { t.settext("la conexión fracasó por:\n\n"); t.append(ex.tostring()); La aplicación todo lo que hace es probar el dsnpubs mostrando el nombre y la versión del gestor de base de datos. Esta aplicación puede servir de plantilla para probar otros DSNs. Objetos básicos de JDBC 160

161 Existen muchos objetos de JDBC, sin embargo, estos tienen vital importancia para empezar a desarrollar nuestras aplicaciones para acceder a base de datos: Connection Permite la conexión a la base de datos. Origina un canal entre nuestra aplicación y la base de datos y será siempre imprescindible en una aplicación para acceder a una base de datos. Statement Este objeto nos permitirá ejecutar una sentencia SQL para nuestra base de datos. Por ejemplo: select, insert, update y delete. ResulSet Si el objeto Statement ejecuta una sentencia select del SQL, entonces, este devuelve un conjunto de resultados. Este conjunto de resultados es asignado y manipulado por un objeto ResulSet. ResultSetMetaData Un objeto de esta clase tiene información meta sobre el conjunto de resultados, como por ejemplo: cuántas columnas tiene la consulta, los nombres de las columnas, los tipos de datos que guarda cada columna, cuántas filas, etc. Para dar ejemplo de los objetos anteriores vamos a desarrollar una aplicación que muestra un formulario con un botón (Consulta a la tabla Authors de la Pubs) y un objeto área de texto que muestra una consulta cuando se da clic al botón. El programa funciona con dsnpubs. La consulta será a la tabla Authors de la base datos Pubs (base de datos de ejemplo que viene con el SQL Server): 161

162 El código de la aplicación esta dado por 2 clases: Formulario y MiPanel. El código de la clase Formulario ya fue creado en el anterior ejemplo y es similar, sin embargo, el código de MiPanel es el siguiente: //Archivo MiPanel import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.sql.*; class MiPanel extends JPanel implements ActionListener { JButton b= new JButton("Consulta a la tabla Authors de la Pubs"); JTextArea t= new JTextArea(); public MiPanel() { setlayout(new BorderLayout()); b.addactionlistener(this); add(b, BorderLayout.NORTH); add(new JScrollPane(t), BorderLayout.CENTER); 162

163 // Para eventos public void actionperformed(actionevent e) { try { Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection cn= DriverManager.getConnection( "jdbc:odbc:dsnpubs", "sa", ""); Statement st= cn.createstatement(); ResultSet rs= st.executequery( "Select au_lname as Apellido," + "au_fname as Nombre," + "phone as Teléfono," + "address as Dirección" + " From Authors"); muestradata(rs); cn.close(); catch(sqlexception ex) { t.settext("error de SQL:\n\n"); t.append(ex.tostring()); catch(exception ex) { t.settext("error genérico:\n\n"); t.append(ex.tostring()); // Auxiliares public void muestradata(resultset r) throws Exception { ResultSetMetaData rmeta= r.getmetadata(); int numcolumnas= rmeta.getcolumncount(); // Cuántas columnas t.settext(""); for(int i=1; i<=numcolumnas; ++i) columna t.append(rmeta.getcolumnname(i) + "\t"); // nombre de t.append("\n"); while(r.next()) { // hasta fin de archivo for(int i=1; i<=numcolumnas; ++i) t.append(r.getstring(i) + "\t"); t.append("\n"); 163

164 Explicacion En este ejemplo mostramos los objetos: Connection (cn), Statement (st) y ResulSet (rs) en una operación conjunta para la consulta a la base de datos. Para acceder a los datos de la consulta necesitamos del objeto ResultSet: ResultSet rs= st.executequery( "Select au_lname as Apellido," + "au_fname as Nombre," + "phone as Teléfono," + "address as Dirección" + " From Authors"); El objeto ResultSet permite acceder a las filas de la consulta mediante una instrucción Select del SQL. Para ejecutar la instrucción Select necesitamos de un objeto Statement: Statement st= cn.createstatement(); Por supuesto para ejecutar un Statement necesitamos previamente de un objeto Connection: Connection cn=drivermanager.getconnection("jdbc:odbc:dsnpubs","sa", ""); El método muestradata es un método personalizado que responde a una instrucción Select. Su construcción se debió a la intención de simplificar y modular la aplicación. El método muestradata como es invocado dentro de una instrucción try tiene que llevar la instrucción: throws Exception. Esto hará que si se produce una excepción en el método entonces se ejecuta la instrucción catch de la instrucción try en la que se invocó al método. En nuestro caso el método muestradata recibe un objeto ResulSet (r) que viene a ser el contenido del objeto rs que tiene la consulta: muestradata(rs); 164

165 Dentro del método muestradata usamos un objeto de la clase ResultSetMetaData con la intención de solicitar información meta de la consulta, como: cuántas columnas hay y cómo se llama cada columna. ResultSetMetaData rmeta= r.getmetadata(); int numcolumnas= rmeta.getcolumncount(); // Cuántas columnas t.settext(""); for(int i=1; i<=numcolumnas; ++i) t.append(rmeta.getcolumnname(i) + "\t"); // nombre de columna Para leer hasta la ultima fila usamos el siguiente código: while(r.next()) { // hasta fin de archivo for(int i=1; i<=numcolumnas; ++i) t.append(r.getstring(i) + "\t"); t.append("\n"); El método next() del ResulSet retorna false cuando no encuentra una fila. También cuando se ejecuta la consulta el objeto ResulSet está antes de la primera fila. Para leer el dato de una columna y retornarlo como un dato de tipo String usamos el método getstring(índice) del objeto ResulSet. Este método requiere como argumento el índice de la columna (1 para la primera) o el nombre de la columna. Conforme se hace lectura a los datos de las columnas del ResultSet, estos datos obtenidos como String son añadidos al objeto JTextArea (t) para que el usuario vea la consulta. DISEÑO GUI CON AWT Y SWING. 165

166 Librería AWT y Swing Swing es un conjunto de clases desarrolladas por primera vez para Java 1.2 (el llamado Java2), para mejorar el anterior paquete que implementaba clases para fabricar interfaces de usuario, el llamado AWT (Abstract Window Tools) que aún se usa bastante en las aplicaciones Java. Tanto Swing como AWT forman parte de una colección de clases llamada JFC (Java Foundation Classes) que incluyen paquetes dedicados a la programación de interfaces gráficos (así como a la producción multimedia). Uno de los problemas frecuentes de la programación clásica era como programar interfaces de usuario, ya que esto implicaba tener que utilizar las API propias del Sistema Operativo y esto provocaba que el código no fuera transportable a otros sistemas. AWT fue la primera solución a este problema propuesta por Java. AWT está formada por un conjunto de clases que no dependen del sistema operativo, pero que proponen una serie de clases para la programación de GUIs (graphic users interfaces, interfaces gráficos de usuario; cualquier entorno de comunicación entre el ordenador y el usuario). AWT usa clases gráficas comunes a todos los sistemas operativos gráficos y luego la máquina virtual traduce esa clase a la forma que tenga en el sistema concreto en el que se ejecutó el programa, sin importar que dicho sistema sea un sistema X, McIntosh o Windows. La popularidad de AWT desbordó las expectativas de la propia empresa Sun. La clave de AWT era el uso de componentes iguales (peers). Los elementos de los interfaces AWT dejaban al sistema la responsabilidad de generar realmente los componentes. Eso aseguraba una vista coherente respecto al sistema en el que se ejecutaba el programa. El problema es que ante la 166

167 grandiosidad de la imagen en Windows y Mac OS, otros sistemas quedaban peor ante la misma aplicación. Por ello (y por otros problemas) aparece Swing en la versión 1.2 como parte del JFC (Java Foundation Classes) que es el kit de clases más importante de Java para las producciones gráficas. Los problemas de AWT eran: AWT tenía problemas de compatibilidad en varios sistemas. A AWT le faltaban algunos componentes avanzados (árboles, tablas,...). Consumía excesivos recursos del sistema. Swing aporta muchas más clases, consume menos recursos y construye mejor la apariencia de los programas. En cualquier caso, AWT no desaparece; simplemente se añade a las nuevas capacidades Swing Componentes Los componentes son los elementos básicos de la programación con Swing. Todo lo que se ve en un GUI de Java es un componente. Los componentes se colocan en otros elementos llamados contenedores que sirven para agrupar componentes. Un administrador de diseño se encarga de de disponer la presentación de los componentes en un dispositivo de presentación concreto. La clase javax.swing.jcomponent es la clase padre de todos los componentes. A su vez, JComponent desciende de java.awt.container y ésta de java.awt.component. De esto se deduce que Swing es una extensión de AWT, de hecho su estructura es análoga. 167

168 La clase JComponent posee métodos para controlar la apariencia del objeto. Por ejemplo: la visibilidad, tamaño, posición, tipo de letra, color,... Al dibujar un componente, se le asigna un dispositivo de presentación. Además posee métodos que controlan el comportamiento del componente. Cuando el usuario ejecuta una acción sobre un componente, entonces se crea un objeto de evento que describe el suceso. El objeto de evento se envía a objetos de control de eventos (Listeners). Los eventos son uno de los pilares de la construcción de Interfaces de usuario y una de las bases de la comunicación entre objetos. 168

169 Pares En AWT se usaban interfaces de pares. Esto significaba que cada componente creado con AWT, creaba un par igual correspondiente al mundo real. Es decir al crear el botón, existía el botón virtual creado en Java y el que realmente era dibujado en la pantalla (el real). El programador no necesita saber de la existencia de ese par, la comunicación del objeto creado con su par corría por cuenta de AWT. Este modelo de componentes se elimina en Swing. En Swing se habla de componentes de peso ligero. La clase JComponent que es la raíz de clases Swing, no utiliza un par, cada componente es independiente del sistema de ventanas principal. Se dibujan a sí mismos y responden a los eventos de usuario sin ayuda de un par. La ventaja de este modelo es que requiere menos recursos y que su modificación visual es más ágil y efectiva. Modelo/vista/controlador Se trata del modelo fundamental del trabajo con interfaces de usuario por parte de Swing. Consiste en tres formas de abstracción. Un mismo objeto se ve de esas tres Formas: Modelo. Se refiere al modelo de datos que utiliza el objeto. Es la información que se manipula mediante el objeto Swing. Vista. Es cómo se muestra el objeto en la pantalla. Controlador. Es lo que define el comportamiento del objeto. Por ejemplo un array de cadenas que contenga los meses del año, podría ser el modelo de un cuadro combinado de Windows. Un cuadro combinado es un rectángulo con un botón con una flecha que permite elegir una opción de una lista. La vista de ese cuadro es el hecho de mostrar esas cadenas en ese rectángulo con flecha. Y el controlador es la capa software que permite capturar el clic del ratón cuando apunta a la flecha del control a fin de mostrar y seleccionar el contenido. 169

170 Métodos de JComponent La clase JComponent es abstracta, lo cual significa que no puede crear objetos, pero sí es la superclase de todos los componentes visuales (botones, listas, paneles, applets,...) y por ello la lista de métodos es interminable, ya que proporciona la funcionalidad de todos los componentes. Además puesto que deriva de Component y Container tiene los métodos de estos, por ello aún es más grande esta lista. Algunos son: Métodos de información Método uso String getname() Obtiene el nombre del componente void setname(string nombre) cambia el nombre del componente Container getparent() Devuelve el contenedor que sostiene a este componente Métodos de apariencia y posición Método void setvisible(boolean vis) Color getforeground() void setforeground(color color) Color getbackground() uso Muestra u oculta el componente según el valor del argumento sea true o false Devuelve el color de frente en forma de objeto Color Cambia el color frontal Devuelve el color de fondo en forma de objeto java.awt.color void setbackground(color color) Cambia el color de fondo Point getlocation() Devuelve la posición del void setlocation(int x, int y) void setlocation(point p) componente en forma de objeto Point Coloca el componente en la posición x, y Coloca el componente en la posición marcada por las coordenadas del punto P Dimension getsize() Devuelve el tamaño del 170

171 void setsize(dimension d) componente en un objeto de tipo java.awt.dimension. Cambia las dimensiones del objeto en base a un objeto Dimension o indicando la anchura y la altura con dos enteros. void setsize(int ancho, int alto) void setbounds(int x, int y, int ancho, int alto) Determina la posición de la void setpreferredsize(dimension d) void settooltiptext(string texto) String gettooltiptext() Cursor getcursor() ventana (en la coordenada x, y) así como su tamaño con los parámetros ancho y alto Cambia el tamaño preferido del componente. Este tamaño es el que el componente realmente quiere tener. Hace que el texto indicado aparezca cuando el usuario posa el cursor del ratón sobre el componente Obtiene el texto de ayuda del componente Obtiene el cursor del componente en forma de objeto java.awt.cursor void setcursor(cursor cursor) Cambia el cursor del void setfont(font fuente) componente por el especificado en el parámetro. Permite especificar el tipo de letra de la fuente del texto Contenedores Son un tipo de componentes pensados para almacenar y manejar otros componentes. Los objetos JComponent pueden ser contenedores al ser una clase que desciende de Container que es la clase de los objetos contenedores de AWT. 171

172 Para hacer que un componente forme parte de un contenedor, se utiliza el método add. Mientras que el método remove es el encargado de eliminar un componente. Ambos métodos proceden de la clase java.awt.container Swing posee algunos contenedores especiales. Algunos son: JWindow. Representa un panel de ventana sin bordes ni elementos visibles. JFrame. Objeto que representa una ventana típica con bordes, botones de cerrar,etc. JPanel. Es la clase utilizada como contenedor genérico para agrupar componentes. JDialog. Clase que genera un cuadro de diálogo. JApplet. Contenedor que agrupa componentes que serán mostrados en un navegador. JWindow Este objeto deriva de la clase java.awt.window que a su vez deriva de java.awt.container. Se trata de un objeto que representa un marco de ventana simple, sin borde, ni ningún elemento. Sin embargo son contenedores a los que se les puede añadir información. Estos componentes suelen estar dentro de una ventana de tipo Frame o, mejor, JFrame. Júrame Los objetos JFrame derivan de la clase Frame que, a su vez deriva, también de la clase Window, por lo que muchos métodos de esta clase son comunes a la anterior. Los objetos JFrame son ventanas completas. JDialog JDialog deriva de la clase AWT Dialog que es subclase de Window. Representa un cuadro de diálogo que es una ventana especializada para realizar operaciones complejas. Añadir componentes a las ventanas 172

173 Las clases JDialog y JFrame no permiten usar el método add, como les ocurre a los contenedores normales, por eso se utiliza el método getcontentpane() que devuelve un objeto Container que representa el área visible de la ventana. A este contenedor se le llama panel contenedor y sí permite método add. public class prbventana{ public static void main(string args[]){ JFrame ventana=new JFrame( Prueba ); ventana.setlocation(100,100); Container c=ventana.getcontentpane(); c.add(new JLabel( Hola )); ventana.pack(); ventana.setvisible(true); Este código muestra una ventana ajustada al contenido de una ventana que pone Hola. Eventos En términos de Java, un evento es un objeto que es lanzado por un objeto y enviado a otro objeto llamado escuchador (listener). Un evento se lanza (o se dispara, fire) cuando ocurre una determinada situación (un clic de ratón, una pulsación de tecla,...). La programación de eventos es una de las bases de Java y permite mecanismos de diseño de programas orientados a las acciones del usuario. Es decir, son las acciones del usuario las que desencadenan mensajes entre los objetos (el flujo del código del programa se desvía en función del evento producido, alterando la ejecución normal). Hay multitud de tipos de eventos, más adelante se señala una lista de los eventos fundamentales. En su captura hay que tener en cuenta que hay tres objetos implicados: 173

174 El objeto fuente. Que es el objeto que lanza los eventos. Dependiendo del tipo de objeto que sea, puede lanzar unos métodos u otros. Por ejemplo un objeto de tipo JLabel (etiqueta) puede lanzar eventos de ratón (MouseEvent) pero no de teclado (KeyEvent). El hecho de que dispare esos eventos no significa que el programa tenga que, necesariamente, realizar una acción. Sólo se ejecuta una acción si hay un objeto escuchando. El objeto escuchador u oyente (listener). Se trata del objeto que recibe el evento producido. Es el objeto que captura el evento y ejecuta el código correspondiente. Para ello debe implementar una interfaz relacionada con el tipo de evento que captura. Esa interfaz obligará a implementar uno o más métodos cuyo código es el que se ejecuta cuando se dispare el evento. El objeto de evento. Se trata del objeto que es enviado desde el objeto fuente al escuchador. Según el tipo de evento que se haya producido se ejecutará uno u otro método en el escuchador. Escuchadores De Eventos Cada tipo de evento tiene asociado un interfaz para manejar el evento. A esos interfaces se les llama escuchadores (Listeners) ya que proporcionan métodos que están a la espera de que el evento se produzca. Cuando el evento es disparado por el objeto fuente al que se estaba escuchando, el método manejador del evento se dispara automáticamente. Por ejemplo, el método actionperformed es el encargado de gestionar eventos del tipo ActionEvent (eventos de acción, se producen, por ejemplo, al hacer clic en un botón). Este método está implementado en la interfaz ActionListener (implementa escuchadores de eventos de acción). Cualquier clase que desee escuchar eventos (los suyos o los de otros objetos) debe implementar la interfaz (o interfaces) pensada para capturar los eventos del 174

175 tipo deseado. Esta interfaz habilita a la clase para poder implementar métodos de gestión de eventos. Por ejemplo; un objeto que quiera escuchar eventos ActionEvent, debe implementar la interfaz ActionListener. Esa interfaz obliga a definir el método ya comentado actionperformed. El código de ese método será invocado automáticamente cuando el objeto fuente produzca un evento de acción. Es decir, hay tres actores fundamentales en el escuchador de eventos: El objeto de evento que se dispara cuando ocurre un suceso. Por ejemplo para capturar el ratón sería MouseEvent. El método o métodos de captura del evento (que se lanza cuando el evento se produce). Pueden ser varios, por ejemplo para la captura de eventos de tipo MouseEvent (evento de ratón) existen los métodos mousereleased (es invocado cuando se libera un botón del ratón), mousepressed (es invocado cuando se pulsa un botón del ratón), mouseentered (es invocado cuando el cursor entra en el objeto) y mouseexited (ocurre cuando el ratón sale del objeto). La interfaz que tiene que estar implementada en la clase que desea capturar ese evento. En este ejemplo sería MouseListener, que es la que obliga a la clase del escuchador a implementar los cuatro métodos de gestión comentados anteriormente Sin duda, el más complejo es este último, pero hay que entender que una internaz lo único que consigue es dar a una clase la facultad de escuchar (Listen) eventos. 175

176 Fuentes De Eventos Disparar eventos El objeto fuente permite que un objeto tenga capacidad de enviar eventos. Esto se consigue mediante un método que comienza por la palabra add seguida por el nombre de la interfaz que captura este tipo de eventos. Este método recibe como parámetro el objeto escuchador de los eventos. Esto es más fácil de lo que parece. Para que un objeto fuente, sea escuchado, hay que indicar quién será el objeto que escuche (que obligadamente deberá implementar la interfaz relacionada con el evento a escuchar). Cualquier componente puede lanzar eventos, sólo hay que indicárselo, y eso es lo que hace el método add. Ejemplo: public class MiVentana extends JFrame implements ActionListener{ JButton boton1=new JButton( Prueba ); //Constructor public MiVentana() { boton1.addactionlistener(this);//el botón lanza //eventos que son capturados por la ventana public void actionperformed(actionevent e){ //Manejo del evento 176

177 En el ejemplo anterior se habilita al boton1 para que lance eventos mediante el método addactionlistener. Este método requiere un objeto escuchador que, en este caso, será la ventana en la que está el botón. Esta ventana tiene que implementar la interfaz ActionListener para poder escuchar eventos (de hecho el método addactionlistener sólo permite objetos de esta interfaz). Cuando se haga clic con el ratón se llamará al método actionperformed de la ventana, que es el método de gestión. Hay que señalar que una misma fuente puede tener varios objetos escuchando los eventos (si lanza varios métodos add). Si hay demasiados objetos escuchando eventos, se produce una excepción del tipo TooManyListenersException eliminar oyentes, Hay un método remove que sirve para que un oyente del objeto deje de escuchar los eventos. boton1.removeactionlistener(this); //La ventana deja de //escuchar los eventos del botón Objeto de evento. Clase EventObject Ya se ha comentado que cuando se produce un evento se crea un objeto llamado objeto de evento. Este objeto es pasado al objeto que está escuchando los eventos. Todos los objetos de evento pertenecen a clases que derivan de EventObject. Esta es la superclase de todos los objetos de evento. Representa un evento genérico y en la práctica sólo sirve para definir los métodos comunes a todos los eventos que son: método Object getsource() uso Obtiene el objeto que lanzó el evento (método muy importante) String tostring() Método tostring redefinido para mostrar la información del evento 177

178 Lanzar Eventos Propios Se pueden crear eventos propios y lanzarlos a cualquier objeto que esté preparado para capturar eventos. Para ello basta crear el evento deseado indicando, al menos, en el constructor el objeto que capturará el evento y el identificador de evento. El identificador es un entero que sirve para indicar el tipo de evento producido. En un evento MouseEvent habrá que indicar si es un evento de clic (MouseEvent.MOUSE_CLICKED), de arrastre (MouseEvent.MOUSEDRAGGED,...). Además según el tipo de evento se pueden requerir más valores (posición del cursor, etc.). En general está técnica sirve para hacer pruebas, pero también se emplea para otros detalles. 178

179 Ejemplo: ventana v1=new ventana(); v1.setlocation(100,100); v1.setsize(300,300); v1.setvisible(true); WindowEvent we=new WindowEvent(v1,WindowEvent.WINDOW_CLOSING); v1.dispatchevent(we); Suponiendo que ventana sea una clase preparada para escuchar eventos de tipo WindowsEvent, se crea el objeto de evento we. El envío del evento se realiza con el método dispachevent. Adaptadores Para facilitar la gestión de eventos en ciertos casos, Java dispone de las llamadas clases adaptadores. Gracias a ellas, en muchos casos se evita tener que crear clases sólo para escuchar eventos. Estas clases son clases de contenido vacío pero que son muy interesantes para capturas sencillas de eventos. Todas poseen la palabra adapter en el nombre de clase. Por ejemplo esta es la definición de la clase MouseAdapter: public abstract class MouseAdapter implements MouseListener { public void mouseclicked(mouseevent e) { public void mousepressed(mouseevent e) { public void mousereleased(mouseevent e) { public void mouseentered(mouseevent e) { public void mouseexited(mouseevent e) { Es una clase que implementa el interfaz MouseListener, pero que no define lo que hace cada método de captura. Eso se suele indicar de manera dinámica: 179

180 JFrame ventana =new JFrame( prueba ); ventana.setlocation(100,100); ventana.setsize(300,300); ventana.setvisible(true); ventana.addmouselistener(new MouseAdapter(){ public void mouseclicked(mouseevent e){ System.out.println( Hola ); ; En el ejemplo anterior al hacer clic en la ventana se escribe el mensaje Hola en la pantalla. No ha hecho falta crear una clase para escuchar los eventos. Se la crea de forma dinámica y se la define en ese mismo momento. La única función del adaptador es capturar los eventos deseados. Otro ejemplo (hola mundo en Swing): import javax.swing.*; import java.awt.*; import java.awt.event.*; public class HolaMundoSwing { public static void main(string[] args) { JFrame frame = new JFrame("HolaMundoSwing"); JLabel label = new JLabel("Hola Mundo"); frame.getcontentpane().add(label); frame.addwindowlistener(new WindowAdapter(){ public void windowclosing(windowevent e){ System.exit(0); ); frame.pack(); frame.setvisible(true); El resultado de ese famoso código es esta ventana: 180

181 El evento windowclosing está capturado por una clase adaptadora, cuya efecto es finalizar el programa cuando se cierra la ventana. Clases adaptadoras: ComponentAdapter ContainerAdapter FocusAdapter InternalFrameAdapter KeyAdapter MouseAdapter MouseMotionAdapter PrintJobAdapter WindowAdapter Mensajes hacia el usuario. clase JOptionPane Una de las labores típicas en la creación de aplicaciones gráficas del tipo que sea, es la de comunicarse con el usuario a través de mensajes en forma de cuadro de diálogo. Algunos cuadros son extremadamente utilizados por su sencillez (textos de aviso, error, confirmación, entrada sencilla de datos, etc.). La clase JOptionPane deriva de JComponent y es la encargada de crear este tipo de cuadros. Aunque posee constructores, normalmente se utilizan mucho más una serie de métodos estáticos que permiten crear de forma más sencilla objetos JOptionPane. Cuadros de información Son cuadros de diálogo que sirven para informar al usuario de un determinado hecho. Se construyen utilizando los siguientes métodos estáticos: 181

182 método static void showmessagedialog( Component padre, Object mensaje) uso Muestra un cuadro de diálogo en el contenedor padre indicado con un determinado mensaje static void showmessagedialog( Component padre, Object mensaje, String título, int tipo) static void showmessagedialog( Component padre, Object mensaje, String título, int tipo, Icon i) Muestra un cuadro de diálogo en el contenedor padre indicado con un determinado mensaje, título y tipo. Igual que el anterior pero se permite indicar un icono para acompañar el mensaje Estos son los posibles creadores de este tipo de cuadro. El tipo puede ser una de estas constantes: JOptionPane.INFORMATION_MESSAGE. JOptionPane.ERROR_MESSAGE. JOptionPane.WARNING_MESSAGE. Aviso JOptionPane.QUESTION_MESSAGE. Pregunta JOptionPane.PLAIN_MESSAGE. Sin icono Ejemplo: JOptionPane.showMessageDialog(this, Soy un mensaje normal, Cuadro 1, JOptionPane.INFORMATION_MESSAGE); 182

Tema 1. Introducción a JAVA

Tema 1. Introducción a JAVA Tema 1. Introducción a JAVA Historia Características Plataforma Java Entorno de desarrollo Ejemplo: Hola mundo Estructura general de un programa Java 1 Historia de Java (i) Surge en 1991: Sun Microsystems

Más detalles

Elementos léxicos del lenguaje de programación Java

Elementos léxicos del lenguaje de programación Java Elementos léxicos del lenguaje de programación Java Elementos léxicos del lenguaje de programación Java Palabras reservadas Identificadores Literales Operadores Delimitadores Comentarios Apéndices Operadores

Más detalles

Identificadores, palabras reservadas, tipos de datos, operadores aritméticos y el sistema estándar de salida en Java

Identificadores, palabras reservadas, tipos de datos, operadores aritméticos y el sistema estándar de salida en Java Identificadores, palabras reservadas, tipos de datos, operadores aritméticos y el sistema estándar de salida en Java Identificadores Las variables se utilizan en programación para almacenar temporalmente

Más detalles

INTRODUCCIÓN A JAVA. Índice

INTRODUCCIÓN A JAVA. Índice INTRODUCCIÓN A JAVA Índice Qué es Java? La plataforma Java 2 La Máquina Virtual de Java Características principales Qué ventajas tengo como desarrollador? Bibliografía 2 1 Qué es Java? La tecnología Java

Más detalles

Tema 2. El lenguaje de programación Java (Parte 1)

Tema 2. El lenguaje de programación Java (Parte 1) Programación en Java Tema 2. El lenguaje de programación Java (Parte 1) Luis Rodríguez Baena Facultad de Informática Elementos del lenguaje (I) El juego de caracteres. No utiliza ASCII, sino Unicode de

Más detalles

Gestor de aplicaciones Java. Esta herramienta es el intérprete de los archivos de clase generados por el javac (compilador).

Gestor de aplicaciones Java. Esta herramienta es el intérprete de los archivos de clase generados por el javac (compilador). CAPÍTULO 4 Requerimientos de software Este capítulo presenta las herramientas necesarias para la construcción y ejecución de programas en el lenguaje de programación JAVA, los requerimientos mínimos de

Más detalles

Objetivo de aprendizaje del tema

Objetivo de aprendizaje del tema Computación II Tema 3. Identificadores, palabras clave y tipos de datos Objetivo de aprendizaje del tema Al finalizar el tema serás capaz de: Distinguir i entre modificadores d válidos y no válidos. Enumerar

Más detalles

Introducción a Java LSUB. 15 de enero de 2015 GSYC

Introducción a Java LSUB. 15 de enero de 2015 GSYC Introducción a LSUB GSYC 15 de enero de 2015 (cc) 2014 Laboratorio de Sistemas, Algunos derechos reservados. Este trabajo se entrega bajo la licencia Creative Commons Reconocimiento - NoComercial - SinObraDerivada

Más detalles

Taller de Programación Estructurada en Java Tema 2. Fundamentos de la programación orientada a objetos

Taller de Programación Estructurada en Java Tema 2. Fundamentos de la programación orientada a objetos Taller de Programación Estructurada en Java Tema 2. Fundamentos de la programación orientada a objetos Ingeniero en Computación José Alfredo Cobián Campos josealfredocobian@gmail.com Facultad de Ciencias

Más detalles

Java en 2 horas. Rodrigo Santamaría

Java en 2 horas. Rodrigo Santamaría + Java en 2 horas Rodrigo Santamaría + Generalidades 2 Desarrollado por Sun en 1995 Hereda mucha de la sintaxis de C (1972) Fuertemente tipado y orientado a objetos Aplicaciones compiladas a bytecode Gestión

Más detalles

Introducción al lenguaje de programación java

Introducción al lenguaje de programación java Introducción al lenguaje de programación java Algoritmia y Programación Slide 1 LENGUAJES DE PROGRAMACION Un lenguaje de programación es un idioma artificial diseñado y creado para expresar algoritmos

Más detalles

www.aprendoencasa.com Curso Introducción JAVA Pág.: 1

www.aprendoencasa.com Curso Introducción JAVA Pág.: 1 www.aprendoencasa.com Curso Introducción JAVA Pág.: 1 Introducción Java es un lenguaje basado en la programación orientada a objetos (POO), este tipo de programación va más allá del tipo de programación

Más detalles

2. Estructura de un programa en Java

2. Estructura de un programa en Java 24 A. García-Beltrán y J.M. Arranz 2. Estructura de un programa en Java Objetivos: a) Describir la estructura del código fuente de una aplicación Java b) Presentar los conceptos de comentario y de identificador

Más detalles

Programación Orientada a Objetos con Java

Programación Orientada a Objetos con Java Programación Orientada a Objetos con Java M.C. Jorge Eduardo Ibarra Esquer jorgeeie@uabc.mx Sobrecarga de métodos Java permite la definición de dos o más métodos que tengan el mismo nombre, dentro de la

Más detalles

Lo que necesitaremos para programar en Java, será un editor de texto o IDE y la JDK.

Lo que necesitaremos para programar en Java, será un editor de texto o IDE y la JDK. Introducción Java surgió en 1991 dentro de la empresa Sun Microsystems como un lenguaje de programación sencillo y universal destinado a electrodomésticos. La reducida potencia de cálculo y memoria de

Más detalles

Repaso de las características más importantes de la programación Java y su adaptación a Android

Repaso de las características más importantes de la programación Java y su adaptación a Android Repaso de las características más importantes de la programación Java y su adaptación a Android 1. Entorno de programación en java 2. Variables y tipos de datos 3. Operaciones y operadores 4. Clases y

Más detalles

Java Inicial (20 horas)

Java Inicial (20 horas) Java Inicial (20 horas) 1 Temario 1. Programación Orientada a Objetos 2. Introducción y Sintaxis Java 3. Sentencias Control Flujo 4. POO en Java 5. Relaciones entre Objetos 6. Polimorfismo, abstracción

Más detalles

INF 473 Desarrollo de Aplicaciones en

INF 473 Desarrollo de Aplicaciones en INF 473 Desarrollo de Aplicaciones en Java Unidad II El Lenguaje de Programación Java Prof. José Miguel Rubio jose.rubio.l@ucv.cl jrubio@inf.ucv.cl PUCV Marzo 2008 1 Orígenes del Lenguaje Java 1991. James

Más detalles

Módulo 1 El lenguaje Java

Módulo 1 El lenguaje Java Módulo 1 El lenguaje 1.1 Presentación de es un lenguaje de programación desarrollado por la empresa Sun Microsystems en 1991 como parte de un proyecto secreto de investigación llamado Green Proyect, con

Más detalles

A continuación resolveremos parte de estas dudas, las no resueltas las trataremos adelante

A continuación resolveremos parte de estas dudas, las no resueltas las trataremos adelante Modulo 2. Inicio con Java Muchas veces encontramos en nuestro entorno referencias sobre Java, bien sea como lenguaje de programación o como plataforma, pero, que es en realidad Java?, cual es su historia?,

Más detalles

Introducción a la Programación en Java. Page 1

Introducción a la Programación en Java. Page 1 Introducción a la Programación en Java Page 1 Qué es Java? Java es un lenguaje de programación de propósito general, orientado a objetos que fue diseñado específicamente para tener tan pocas dependencias

Más detalles

Introducción a la programación orientada a objetos

Introducción a la programación orientada a objetos Introducción a la programación orientada a objetos 1. Introducción a la programación orientada a objetos 2. Las clases 3. El tipo Struct 4. Diferencias entre Class y Struct 5. Pilares de la Programación

Más detalles

Modulo 1 El lenguaje Java

Modulo 1 El lenguaje Java Modulo 1 El lenguaje Java 13 - Codificación en Java Una de las grandes diferencias entre Java y Pascal en cuando a la codificación es que Java se trata de un lenguaje de los llamados case sensitive Esto

Más detalles

RESUMEN DE CONCEPTOS BASICOS DE PROGRAMACION JAVA

RESUMEN DE CONCEPTOS BASICOS DE PROGRAMACION JAVA UNED Centro Asociado de Cádiz RESUMEN DE CONCEPTOS BASICOS DE PROGRAMACION JAVA 1. OBJETOS Cualquier elemento del programa es un objeto. Un programa es un conjunto de objetos que se comunican entre sí

Más detalles

CONCEPTOS BASICOS DEL LENGUAJE JAVA

CONCEPTOS BASICOS DEL LENGUAJE JAVA CONCEPTOS BASICOS DEL LENGUAJE JAVA NOMENCLATURA GENERAL En Java se distinguen las letras mayúsculas y minúsculas. Las reglas del lenguaje respecto a los nombres de variables son muy amplias y permiten

Más detalles

Java en 3 horas. Ampliación de Sistemas Operativos. Rodrigo Santamaría

Java en 3 horas. Ampliación de Sistemas Operativos. Rodrigo Santamaría Java en 3 horas Ampliación de Sistemas Operativos Rodrigo Santamaría Generalidades Desarrollado por Sun Hereda mucha de la sintaxis de C (1972) Fuertemente tipado y orientado a objetos Aplicaciones compiladas

Más detalles

JavaScript. Contenidos. Introducción El lenguaje Validación de formularios. Programación en Internet 2005-2006. DLSI - Universidad de Alicante 1

JavaScript. Contenidos. Introducción El lenguaje Validación de formularios. Programación en Internet 2005-2006. DLSI - Universidad de Alicante 1 Departamento de Lenguajes y Sistemas Informáticos JavaScript Programación en Internet Curso 2005-2006 Contenidos Introducción El lenguaje Validación de formularios DLSI - Universidad de Alicante 1 Introducción

Más detalles

Introducción... 1 Qué es Java?... 1 Compilando a Bytecode... 1 Usando jgrasp Para Hacer el Trabajo Sucio... 5 El Entorno de jgrasp...

Introducción... 1 Qué es Java?... 1 Compilando a Bytecode... 1 Usando jgrasp Para Hacer el Trabajo Sucio... 5 El Entorno de jgrasp... Contenido Introducción... 1 Qué es Java?... 1 Compilando a Bytecode... 1 Usando jgrasp Para Hacer el Trabajo Sucio... 5 El Entorno de jgrasp... 5 Introducción Es tiempo de hablar en detalle de lo que significa

Más detalles

Sensor de Temperatura utilizando el Starter Kit Javelin Stamp. Realizado por: Bertha Palomeque A. Rodrigo Barzola J.

Sensor de Temperatura utilizando el Starter Kit Javelin Stamp. Realizado por: Bertha Palomeque A. Rodrigo Barzola J. Sensor de Temperatura utilizando el Starter Kit Javelin Stamp Realizado por: Bertha Palomeque A. Rodrigo Barzola J. INTRODUCCION DIFERENCIAS EJEMPLOS JAVA Orientado a Objetos Multiplataforma Programar

Más detalles

Modelo de Objetos Distribuidos

Modelo de Objetos Distribuidos Remote Method Invocation Modelo de Objetos Distribuidos Un objeto remoto es un objeto cuyos métodos pueden ser invocados desde otra máquina virtual de java, potencialmente en un host diferente. Modelo

Más detalles

Internet Information Server

Internet Information Server Internet Information Server Internet Information Server (IIS) es el servidor de páginas web avanzado de la plataforma Windows. Se distribuye gratuitamente junto con las versiones de Windows basadas en

Más detalles

9. Objetos y clases. 9.1. Clases

9. Objetos y clases. 9.1. Clases Programación orientada a objetos con Java 103 9. Objetos y clases Objetivos: a) Presentar el concepto de objeto, clase, atributo, método e instancia b) Interpretar el código fuente de una aplicación Java

Más detalles

Curso de Java POO: Programación orientada a objetos

Curso de Java POO: Programación orientada a objetos Curso de Java POO: Programación orientada a objetos Luis Guerra Velasco Curso INEM 02830. Programación en Java Marzo 2010 Índice 1 Introducción a la POO 2 Herencia y polimorfismo 3 Empaquetado de proyectos

Más detalles

INTELIGENCIA ARTIFICIAL 2015 TALLER RÁPIDO DE PROGRAMACIÓN EN JAVA

INTELIGENCIA ARTIFICIAL 2015 TALLER RÁPIDO DE PROGRAMACIÓN EN JAVA INTELIGENCIA ARTIFICIAL 2015 TALLER RÁPIDO DE PROGRAMACIÓN EN JAVA Fuente: http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html Por qué Java? TIOBE Index for March 2015 Fuente: http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html

Más detalles

El lenguaje de programación Java

El lenguaje de programación Java Departament d Arquitectura de Computadors El lenguaje de programación Java Java (I) Orientado a objetos Ejecutado por una maquina virtual Independiente de la plataforma Multithreaded Orientado a la red

Más detalles

(volver a Tabla de Contenidos)

(volver a Tabla de Contenidos) Para escribir, compilar y ejecutar un programa en Java lo único que realmente se necesita y no viene incluido con el sistema operativo es el kit de desarrollo de Java, denominado SDK (Software Development

Más detalles

AGREGAR COMPONENTES ADICIONALES DE WINDOWS

AGREGAR COMPONENTES ADICIONALES DE WINDOWS INSTALACIÓN DE IIS EN WINDOWS XP El sistema está desarrollado para ejecutarse bajo la plataforma IIS de Windows XP. Por esta razón, incluimos la instalación de IIS (Servidor de Web) para la correcta ejecución

Más detalles

TEMA 2. Agenda. Fundamentos de JAVA

TEMA 2. Agenda. Fundamentos de JAVA TEMA 2 Fundamentos de JAVA V1.3 Manuel Pereira González Agenda Introducción Historia de Java Características Principales Hello World Tipos Operadores Control de Flujo E/S básica Atributos y Métodos Resumen

Más detalles

Objetivo: Introducción conceptual y aplicación básica de los lenguajes del lado del servidor.

Objetivo: Introducción conceptual y aplicación básica de los lenguajes del lado del servidor. Sesión 03: Lenguajes web del servidor Competencias a Conseguir: - Conocer el entorno de trabajo a nivel de servidores web. - Instalación del localhost (Servidor Local). - Repaso general de PHP y ejercicios

Más detalles

Programador en Plataforma Java y XML

Programador en Plataforma Java y XML Programador en Plataforma Java y XML Java Fundamentos Módulo 1: Java Básico Introducción En la presente unidad, se detalla los fundamentos de la tecnología Java, reconociendo las 3 plataformas que la conforman.

Más detalles

Preliminares. Tipos de variables y Expresiones

Preliminares. Tipos de variables y Expresiones Preliminares. Tipos de variables y Expresiones Felipe Osorio Instituto de Estadística Pontificia Universidad Católica de Valparaíso Marzo 5, 2015 1 / 20 Preliminares Computadoras desarrollan tareas a un

Más detalles

Anexo B. Comunicaciones entre mc y PC

Anexo B. Comunicaciones entre mc y PC Anexo B Comunicaciones entre mc y PC En este apartado se hará hincapié en los comandos para el manejo del módulo de comunicaciones desde el PC. Conociendo estos comando se podrá realizar una aplicación

Más detalles

Módulo 2. Inicio con Java

Módulo 2. Inicio con Java Módulo 2. Inicio con Java Objetivos: -Clasificar el lenguaje de programación Java según las formas de clasificar los lenguajes de programación. -Describir el funcionamiento de la plataforma Java. -Explicar

Más detalles

Primera Escuela de la Red Temática SVO. Madrid, 27-28 Noviembre, 2006 JAVA BÁSICO. Raúl Gutiérrez Sánchez LAEFF - INTA raul@laeff.inta.

Primera Escuela de la Red Temática SVO. Madrid, 27-28 Noviembre, 2006 JAVA BÁSICO. Raúl Gutiérrez Sánchez LAEFF - INTA raul@laeff.inta. Primera Escuela de la Red Temática SVO. Madrid, 27-28 Noviembre, 2006 JAVA BÁSICO LAEFF - INTA raul@laeff.inta.es Qué es Java? Java es un lenguaje de programación orientado a objetos desarrollado por Sun

Más detalles

Ejercicios - Persistencia en Android: ficheros y SQLite

Ejercicios - Persistencia en Android: ficheros y SQLite Ejercicios - Persistencia en Android: ficheros y SQLite Índice 1 Uso de ficheros (0.5 puntos)...2 2 Persistencia con ficheros (0.5 puntos)...3 3 Base de datos: SQLiteOpenHelper (0.5 puntos)... 3 4 Base

Más detalles

19. Packages o paquetes

19. Packages o paquetes Programación orientada a objetos con Java 201 19. Packages o paquetes Objetivos: a) Definir el concepto de paquete b) Interpretar el código fuente de una aplicación Java donde se utilicen paquetes c) Construir

Más detalles

Compilación y ejecución de programas en Java.

Compilación y ejecución de programas en Java. Java Virtual Machine La mayoría de los lenguajes de programación se caracterizan por ser interpretados o compilados, lo que determina la manera en como serán ejecutados en una computadora. Java tiene la

Más detalles

Introduccion al Lenguaje C. Omar Andrés Zapata Mesa Grupo de Fenomenología de Interacciones Fundamentales, (Gfif) Universidad de Antioquia

Introduccion al Lenguaje C. Omar Andrés Zapata Mesa Grupo de Fenomenología de Interacciones Fundamentales, (Gfif) Universidad de Antioquia Introduccion al Lenguaje C Omar Andrés Zapata Mesa Grupo de Fenomenología de Interacciones Fundamentales, (Gfif) Universidad de Antioquia Introducción C es un lenguaje de programación creado en 1972 por

Más detalles

Unidad I. 1.1 Sistemas numéricos (Binario, Octal, Decimal, Hexadecimal)

Unidad I. 1.1 Sistemas numéricos (Binario, Octal, Decimal, Hexadecimal) Unidad I Sistemas numéricos 1.1 Sistemas numéricos (Binario, Octal, Decimal, Hexadecimal) Los computadores manipulan y almacenan los datos usando interruptores electrónicos que están ENCENDIDOS o APAGADOS.

Más detalles

Tarea 1 Programación José Luis Comesaña

Tarea 1 Programación José Luis Comesaña Para la descarga de Java he optado por dirigirme a su propietario ORACLE para iniciar la grabación desde su página oficial: http://www.oracle.com/es/index.html donde seleccionamos Java 2 en el apartado

Más detalles

En cualquier caso, tampoco es demasiado importante el significado de la "B", si es que lo tiene, lo interesante realmente es el algoritmo.

En cualquier caso, tampoco es demasiado importante el significado de la B, si es que lo tiene, lo interesante realmente es el algoritmo. Arboles-B Características Los árboles-b son árboles de búsqueda. La "B" probablemente se debe a que el algoritmo fue desarrollado por "Rudolf Bayer" y "Eduard M. McCreight", que trabajan para la empresa

Más detalles

Tema 3 Elementos básicos de programación

Tema 3 Elementos básicos de programación Representación de Datos y Aplicaciones Tema 3 Elementos básicos de programación Natividad Martínez Madrid nati@it.uc3m.es Objetivos del tema 3 Conocer la estructura básica de un programa Java Comprender

Más detalles

Ayuda para la instalación Componente Firma Digital INDICE. 1 Configuración previa...2. 1.1 Configuración Internet Explorer para ActiveX...

Ayuda para la instalación Componente Firma Digital INDICE. 1 Configuración previa...2. 1.1 Configuración Internet Explorer para ActiveX... INDICE 1 Configuración previa...2 1.1 Configuración Internet Explorer para ActiveX...2 1.2 Problemas comunes en sistema operativo Windows...8 1.2.1 Usuarios con sistema operativo Windows XP con el Service

Más detalles

Software Criptográfico FNMT-RCM

Software Criptográfico FNMT-RCM Software Criptográfico FNMT-RCM ÍNDICE 1. DESCARGA E INSTALACIÓN DEL SOFTWARE 2. EXPORTACIÓN DE CERTIFICADOS EN MICROSOFT INTERNET EXPLORER 3. IMPORTACIÓN DEL CERTIFICADO A LA TARJETA CRIPTOGRÁFICA -2-

Más detalles

GUÍA Nro. 1 TECNOLOGÍA DE INTERNET. TIII PIII

GUÍA Nro. 1 TECNOLOGÍA DE INTERNET. TIII PIII GUÍA Nro. 1 TECNOLOGÍA DE INTERNET. TIII PIII GUIA DISPONIBLE EN: http://preparadorivan.blogspot.com/ - http://preparadormssi.50webs.com/inicio.html La World Wide Web o la Web, es una de las múltiples

Más detalles

INDICE DEL CURSO APRENDER PROGRAMACIÓN JAVA DESDE CERO. PROGRAMACIÓN ORIENTADA A OBJETOS (CU00601B)

INDICE DEL CURSO APRENDER PROGRAMACIÓN JAVA DESDE CERO. PROGRAMACIÓN ORIENTADA A OBJETOS (CU00601B) APRENDERAPROGRAMAR.COM INDICE DEL CURSO APRENDER PROGRAMACIÓN JAVA DESDE CERO. PROGRAMACIÓN ORIENTADA A OBJETOS (CU00601B) Sección: Cursos Categoría: Curso Aprender programación Java desde cero Fecha revisión:

Más detalles

Clases y Objetos. Informática II Ingeniería Electrónica

Clases y Objetos. Informática II Ingeniería Electrónica Clases y Objetos Informática II Ingeniería Electrónica Los Tipos de Datos Hasta ahora, en un programa podemos usar para representar variables a: Tipos fundamentales : enteros (int), caracteres (char),

Más detalles

WINDOWS 2008 7: COPIAS DE SEGURIDAD

WINDOWS 2008 7: COPIAS DE SEGURIDAD 1.- INTRODUCCION: WINDOWS 2008 7: COPIAS DE SEGURIDAD Las copias de seguridad son un elemento fundamental para que el trabajo que realizamos se pueda proteger de aquellos problemas o desastres que pueden

Más detalles

ENVÍO DE E-MAIL POR MEDIO DE SMTP

ENVÍO DE E-MAIL POR MEDIO DE SMTP UNIVERSIDAD TÉCNICA FEDERICO SANTA MARÍA DEPARTAMENTO DE ELECTRÓNICA ELO 322: REDES DE COMPUTADORES I ENVÍO DE E-MAIL POR MEDIO DE SMTP Alumnos Ariel Mancilla G. 2521040-9 Daniel Spataris J. 2521029-8

Más detalles

PART II: Moviendo al jugador

PART II: Moviendo al jugador UNITY PART II: Moviendo al jugador El movimiento se lo vamos a dar a través de un programa Definición de programa: Un programa es una secuencia de instrucciones, escritas para realizar una tarea específica

Más detalles

by Tim Tran: https://picasaweb.google.com/lh/photo/sdo00o8wa-czfov3nd0eoa?full-exif=true

by Tim Tran: https://picasaweb.google.com/lh/photo/sdo00o8wa-czfov3nd0eoa?full-exif=true by Tim Tran: https://picasaweb.google.com/lh/photo/sdo00o8wa-czfov3nd0eoa?full-exif=true I. FUNDAMENTOS 3. Representación de la información Introducción a la Informática Curso de Acceso a la Universidad

Más detalles

Programación orientada a objetos

Programación orientada a objetos Repaso Programación orientada a objetos Curso INEM. Programación en Java Santiago Muelas Pascual smuelas@fi.upm.es! Clase! Objeto! Atributo o variable de instancia! Método! Instanciar/crear un objeto!

Más detalles

Tema 1: y el lenguaje Java 1.Programación orientada a objetos 2.El lenguaje Java 3.Compilación, bytecode y JVMs 4.Entornos de desarrollo Java 5.Java vs otros lenguajes OO Programación orientada a objetos

Más detalles

8. Sentencia return y métodos

8. Sentencia return y métodos 92 A. García-Beltrán y J.M. Arranz 8. Sentencia return y métodos Objetivos: a) Describir el funcionamiento de la sentencia return b) Interpretar el resultado de una sentencia return en el código fuente

Más detalles

WINDOWS 2008 5: TERMINAL SERVER

WINDOWS 2008 5: TERMINAL SERVER WINDOWS 2008 5: TERMINAL SERVER 1.- INTRODUCCION: Terminal Server proporciona una interfaz de usuario gráfica de Windows a equipos remotos a través de conexiones en una red local o a través de Internet.

Más detalles

2.1. Introducción al lenguaje Java

2.1. Introducción al lenguaje Java Bloque II. Elementos del lenguaje de programación Java 1.Introducción a los lenguajes de programación 2. Estructura de un programa 3. Datos y expresiones simples 4. Instrucciones de control 5. Entrada/salida

Más detalles

Acronis License Server. Guía del usuario

Acronis License Server. Guía del usuario Acronis License Server Guía del usuario TABLA DE CONTENIDO 1. INTRODUCCIÓN... 3 1.1 Generalidades... 3 1.2 Política de licencias... 3 2. SISTEMAS OPERATIVOS COMPATIBLES... 4 3. INSTALACIÓN DE ACRONIS LICENSE

Más detalles

Parámetros con la ventana de selección de usuario, reglas, texto y descomposición (IVE)

Parámetros con la ventana de selección de usuario, reglas, texto y descomposición (IVE) QUÉ SON CONCEPTOS PARAMÉTRICOS? Los conceptos paramétricos de Presto permiten definir de una sola vez una colección de conceptos similares a partir de los cuales se generan variantes o conceptos derivados

Más detalles

Programación Orientada a Objetos en Java

Programación Orientada a Objetos en Java Programación Orientada a Objetos en Java Curso 2006-2007 Tema 4 Herencia y Polimorfismo Gonzalo Méndez Pozo Dpto. de Ingeniería de Software e Inteligencia Artificial Universidad Complutense de Madrid Herencia

Más detalles

Seminario de Java. Contenido

Seminario de Java. Contenido Seminario de Java Programación Orientada a Objetos Curso 2006/2007 Contenido 1. Introducción 2. Primeros pasos con Java. El entorno Eclipse 3. La sintaxis del lenguaje Java 4. Clases y objetos 5. Cadenas

Más detalles

Curso de PHP con MySQL Gratis

Curso de PHP con MySQL Gratis Curso de PHP con MySQL Gratis Introducción Este mini curso o mini tutorial de PHP le ayudará a realizar cualquier sistema para que pueda insertar uno o varios registros a una base de datos con MySQL, este

Más detalles

Carmen. Estándares de codificación. Manuel Arias Calleja

Carmen. Estándares de codificación. Manuel Arias Calleja Carmen. Estándares de codificación Manuel Arias Calleja II Índice general 1. Estandares de codificación 1 1.1. Nombres de ficheros........................ 1 1.2. Organización de ficheros......................

Más detalles

Java. Mtro. Manuel Suárez Gutiérrez

Java. Mtro. Manuel Suárez Gutiérrez Java Mtro. Manuel Suárez Gutiérrez Introducción Creado por SUN Microsystems Su fin era homologar los lenguajes de programación ante una proliferación de multiples plataformas Trabaja bajo una maquina virtual

Más detalles

Plataforma e-ducativa Aragonesa. Manual de Administración. Bitácora

Plataforma e-ducativa Aragonesa. Manual de Administración. Bitácora Plataforma e-ducativa Aragonesa Manual de Administración Bitácora ÍNDICE Acceso a la administración de la Bitácora...3 Interfaz Gráfica...3 Publicaciones...4 Cómo Agregar una Publicación...4 Cómo Modificar

Más detalles

1. El entorno de desarrollo Eclipse

1. El entorno de desarrollo Eclipse Índice 1. El entorno de desarrollo Eclipse 1 1.1. Qué es Eclipse?........................................................ 1 1.2. Trabajando con Eclipse....................................................

Más detalles

COPIAS DE SEGURIDAD AUTOMÁTICAS DE DIRECCIONES CALLEÇPAÑA

COPIAS DE SEGURIDAD AUTOMÁTICAS DE DIRECCIONES CALLEÇPAÑA COPIAS DE SEGURIDAD AUTOMÁTICAS DE DIRECCIONES CALLEÇPAÑA Autor: Carlos Javier Martín González. Licenciado en Física Teórica por la Universidad Autónoma de Madrid. Analista programador y funcional. Desarrollador

Más detalles

Pontificia Universidad Católica de Chile Escuela de Ingeniería Departamento de Ciencia de la Computación. IIC1102 Introducción a la Programación

Pontificia Universidad Católica de Chile Escuela de Ingeniería Departamento de Ciencia de la Computación. IIC1102 Introducción a la Programación Pontificia Universidad Católica de Chile Escuela de Ingeniería Departamento de Ciencia de la Computación IIC1102 Introducción a la Programación Tutorial eclipse TM Introducción al uso de eclipse TM Contents

Más detalles

Tema 1. Representación de la información MME 2012-20131

Tema 1. Representación de la información MME 2012-20131 Tema 1 Representación de la información 1 Índice Unidad 1.- Representación de la información 1. Informática e información 2. Sistema de numeración 3. Representación interna de la información 2 Informática

Más detalles

SISTEMAS DE NUMERACIÓN. Sistema decimal

SISTEMAS DE NUMERACIÓN. Sistema decimal SISTEMAS DE NUMERACIÓN Sistema decimal Desde antiguo el Hombre ha ideado sistemas para numerar objetos, algunos sistemas primitivos han llegado hasta nuestros días, tal es el caso de los "números romanos",

Más detalles

JAVA PARA PRINCIPIANTES

JAVA PARA PRINCIPIANTES UN POCO DE HISTORIA Java fue creado en 1991 por James Gosling de Sun Microsystems inicialmente llamado Oak que significa roble, esto debido a la cantidad de arboles que rodeaban el sitio donde este trabajaba.

Más detalles

TUTORIAL DE INSTALACIÓN Y CONFIGURACIÓN DE NETBEANS

TUTORIAL DE INSTALACIÓN Y CONFIGURACIÓN DE NETBEANS TUTORIAL DE INSTALACIÓN Y CONFIGURACIÓN DE NETBEANS Apartado A: Descarga desde la web oficial de Oracle, Java SE e instálalo en tu equipo. Vamos a la página web de Oracle, y seleccionamos en productos

Más detalles

Práctica 3 mtp. metodoloxía e tecnoloxía da programación. Presentar detalles básicos sobre la sintaxis del lenguaje de programación Java.

Práctica 3 mtp. metodoloxía e tecnoloxía da programación. Presentar detalles básicos sobre la sintaxis del lenguaje de programación Java. Práctica 3 mtp metodoloxía e tecnoloxía da programación Objetivos: Duración: Presentar detalles básicos sobre la sintaxis del lenguaje de programación Java. 1 semana 1.- Identificadores Los identificadores

Más detalles

Java Básico. Introducción a Java. Copyright

Java Básico. Introducción a Java. Copyright Java Básico Introducción a Java Copyright Copyright (c) 2004 José M. Ordax Este documento puede ser distribuido solo bajo los términos y condiciones de la Licencia de Documentación de javahispano v1.0

Más detalles

Ingº CIP Fabian Guerrero Medina Master Web Developer-MWD

Ingº CIP Fabian Guerrero Medina Master Web Developer-MWD 1 Java es un lenguaje de programación de Sun Microsystems originalmente llamado "Oak. James Gosling Bill Joy 2 Oak nació para programar pequeños dispositivos electrodomésticos, como los asistentes personales

Más detalles

UNIVERSIDAD CATOLICA DE COLOMBIA FACULTAD DE INGENIERIA DE SISTEMAS

UNIVERSIDAD CATOLICA DE COLOMBIA FACULTAD DE INGENIERIA DE SISTEMAS UNIVERSIDAD CATOLICA DE COLOMBIA FACULTAD DE INGENIERIA DE SISTEMAS CURSO: PROFESOR: JAVA BASICO EMERSON CASTAÑEDA SANABRIA TEMA: Introducción a Java OBJETIVOS: Conocer como se origino el lenguaje de programación

Más detalles

CONCEPTOS BASICOS. Febrero 2003 Página - 1/10

CONCEPTOS BASICOS. Febrero 2003 Página - 1/10 CONCEPTOS BASICOS Febrero 2003 Página - 1/10 EL ESCRITORIO DE WINDOWS Se conoce como escritorio la zona habitual de trabajo con windows, cuando iniciamos windows entramos directamente dentro del escritorio,

Más detalles

Sintaxis y Convenciones de Java. M. en C. Erika Vilches

Sintaxis y Convenciones de Java. M. en C. Erika Vilches Sintaxis y Convenciones de Java M. en C. Erika Vilches Estructura del Código en Java Hay una clase en un archivo fuente Hay métodos en una clase Hay enunciados en un método Anatomía de una Clase Cuando

Más detalles

Para leer la entrada de consola, lo primero que se hace es construir un Scanner que este asociado al flujo de entrada estándar System.

Para leer la entrada de consola, lo primero que se hace es construir un Scanner que este asociado al flujo de entrada estándar System. CICLO: 01/2010 Universidad Don Bosco Materia: Lenguaje de Programación III Contenido: 1-Lectura de Datos de entrada. 2-Introduccion a JOPTIONPANE. 3-Estructuras de Control. ->LECTURA DE DATOS DE ENTRADA

Más detalles

FUNDAMENTOS DE PROGRAMACION CON C#

FUNDAMENTOS DE PROGRAMACION CON C# Capítulo 1 FUNDAMENTOS DE PROGRAMACION CON C# El lenguaje C# C# (léase, en inglés C sharp, y en español C almohadilla) es un lenguaje de programación que permite el desarrollo de aplicaciones para Internet,

Más detalles

GESTIÓN DE EXCEPCIONES EN JAVA. CAPTURA CON BLOQUES TRY CATCH Y FINALLY. EJEMPLOS RESUELTOS. (CU00927C)

GESTIÓN DE EXCEPCIONES EN JAVA. CAPTURA CON BLOQUES TRY CATCH Y FINALLY. EJEMPLOS RESUELTOS. (CU00927C) APRENDERAPROGRAMAR.COM GESTIÓN DE EXCEPCIONES EN JAVA. CAPTURA CON BLOQUES TRY CATCH Y FINALLY. EJEMPLOS RESUELTOS. (CU00927C) Sección: Cursos Categoría: Lenguaje de programación Java nivel avanzado I

Más detalles

Programación Avanzada para Sistemas de Telecomunicación. Objetos y clases. J.C. Cruellas. Objetos y clases

Programación Avanzada para Sistemas de Telecomunicación. Objetos y clases. J.C. Cruellas. Objetos y clases Programación Avanzada para Sistemas de Telecomunicación Objetos y clases Juan Carlos Cruellas cruellas@ac.upc.es Objetos y clases Concepto de objeto. Concepto de clase. Clases, objetos y programas. Clases

Más detalles

TIPOS DE VARIABLES EN PHP. DECLARACIÓN Y ASIGNACIÓN. LA INSTRUCCIÓN ECHO PARA INSERTAR TEXTO O CÓDIGO. (CU00816B)

TIPOS DE VARIABLES EN PHP. DECLARACIÓN Y ASIGNACIÓN. LA INSTRUCCIÓN ECHO PARA INSERTAR TEXTO O CÓDIGO. (CU00816B) APRENDERAPROGRAMAR.COM TIPOS DE VARIABLES EN PHP. DECLARACIÓN Y ASIGNACIÓN. LA INSTRUCCIÓN ECHO PARA INSERTAR TEXTO O CÓDIGO. (CU00816B) Sección: Cursos Categoría: Tutorial básico del programador web:

Más detalles

PROGRAMACIÓ DIDÁCTICA: Secuanciación, Temporalización y Unidades Didácticas

PROGRAMACIÓ DIDÁCTICA: Secuanciación, Temporalización y Unidades Didácticas Departamento de Informática PROGRAMACIÓN DIDÁCTICA Curso 11-12 1 CONSEJERÍA DE EDUCACIÓN I.E.S. NERVIÓN Departamento de Informática CICLO FORMATIVO: TÉCNICO SUPERIOR EN DESARROLLO DE APLICACIONES MULTIPLATAFORMA.

Más detalles

Programación Orientada a Objetos. Java: Excepciones

Programación Orientada a Objetos. Java: Excepciones Programación Orientada a Objetos Java: Excepciones Eduardo Mosqueira Rey LIDIA Laboratorio de Investigación y desarrollo en Inteligencia Artificial Departamento de Computación Universidade da Coruña, España

Más detalles

Manual hosting acens

Manual hosting acens Manual hosting acens Contenido Acceso al panel de control de cliente... 3 Asociar un dominio a mi Hosting... 5 Acceso al panel de administración del hosting... 7 INICIO - Visión general del estado de nuestro

Más detalles

MANUAL COPIAS DE SEGURIDAD

MANUAL COPIAS DE SEGURIDAD MANUAL COPIAS DE SEGURIDAD Índice de contenido Ventajas del nuevo sistema de copia de seguridad...2 Actualización de la configuración...2 Pantalla de configuración...3 Configuración de las rutas...4 Carpeta

Más detalles

Capitulo 5. Implementación del sistema MDM

Capitulo 5. Implementación del sistema MDM Capitulo 5. Implementación del sistema MDM Una vez que se concluyeron las actividades de análisis y diseño se comenzó la implementación del sistema MDM (Manejador de Documentos de MoProSoft). En este capitulo

Más detalles

Instalar protocolo, cliente o servicio nuevo. Seleccionar ubicación de red. Práctica - Compartir y conectar una carpeta

Instalar protocolo, cliente o servicio nuevo. Seleccionar ubicación de red. Práctica - Compartir y conectar una carpeta Configuración de una red con Windows Aunque existen múltiples sistemas operativos, el más utilizado en todo el mundo sigue siendo Windows de Microsoft. Por este motivo, vamos a aprender los pasos para

Más detalles

1. Aplicaciones del J2SE SDK1.4.2 de Sun.

1. Aplicaciones del J2SE SDK1.4.2 de Sun. Dept Informatica Índice 1 Aplicaciones del J2SE SDK142 de Sun 1 11 javac 1 12 java 1 13 javadoc 2 14 Las que no se explican 3 2 Guía de estilo de Java 3 21 Clases 3 211 Nombres para las clases 3 212 Estructura

Más detalles

Creación y administración de grupos de dominio

Creación y administración de grupos de dominio Creación y administración de grupos de dominio Contenido Descripción general 1 a los grupos de Windows 2000 2 Tipos y ámbitos de los grupos 5 Grupos integrados y predefinidos en un dominio 7 Estrategia

Más detalles