Java Resumen

Embed Size (px)

Citation preview

Multihilamientos por Jairo Gonzalez [email protected] Java soporta programacin con mltiples hilos que significa que varias secuencias de ejecucin corren simultneamente dentro de un mismo proceso. Hay que diferenciar con el trmino multitarea que significa que varios procesos corren simultneamente en la misma mquina. Los elementos claves para hacer el manejo de hilos dentro de una aplicacion son una clase y una interfaz que se usan correspondientemente segun el caso que se tenga en frente. La interfaz java.lang.Runnable y la clase java.lang.Thread Yo puedo crear un hilo instanciando la clase Thread o haciendo que una de mis clases implemente la interfaz Runnable. Cuando se implementa la interfaz Runnable, como se recuerda, el programador queda obligado a crear un mtodo llamado run (para ms informacin ver la definicin de la interfazjava.lang.Runnable). En el interior del mtodo run se le programa al hilo lo que tiene que hacer. Existen dos formas para proveer un mtodo run para un hilo: y y Haciendo una subclase de Thread y sobrecargando run (sobrecargando significa sobreescribiendo el mtodo luego de heredar la clase) Implementando la interface Runnable

Runnable es una interfaz simple que abstrae la nocin de que se desea que algn cdigo se "ejecute" asincrnicamente. Para implementar Runnable, a una clase le basta con implementar un solo mtodo llamado run. Este es un ejemplo que crea un nuevo hilo. EJEMPLO public class Reloj2 implements Runnable { public Reloj2() { Thread ct = Thread.currentThread(); Thread t = new Thread(this, "demo Thread"); System.out.println("hilo actual: " + ct); System.out.println("Hilo creado: " + t); t.start(); try { for (int i=0; i 0; y--) { System.out.println(" " + y); Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("hijo interrumpido"); { // mtodo obligatorio por el uso de la interfaz Runnable

}

} System.out.println("saliendo del hilo hijo"); } public static void main (String args []) new Reloj2(); } } El hilo main crea un nuevo objeto Thread, con new Thread (this, "Demo Thread"), pasando this como primer argumento para indicar que queremos que el nuevo hilo llame al mtodo run sobre este (this) objeto, es decir queremos que el nuevo hilamiento sea hijo del actual. A continuacin llamamos a start, lo que inicia el hilo de la ejecucin a partir del mtodo run. Despus, el hilo main se duerme durante 1000 milisegundos antes de imprimir un mensaje y despus termina. Demo Thread todava est contando desde cinco cuando sucede esto. Se contina ejecutando hasta que termina con el bucle de run. Esta es la salida despus de cinco segundos: Hilo actual: Thread[main, 5, main] Hilo creado: Thread[demo Thread, 5, main] 5 4 *0 3 *1 2 *2 1 *3 saliendo del hilo hijo *4 saliendo del hilo main El ciclo de vida de un hilo. Ahora veremos las caractersticas de un hilo, podemos crear, arrancar y detenerlo, as como ver como se pueden modificar su nivel de prioridad. Prioridades. La gran ventaja que ofrecen los hilos consiste en que se ejecutan de manera concurrente. Conceptualmente, esto es cierto, pero en la prctica generalmente no es posible, se van multiplexando en la ejecucin. La mayora de las computadoras tienen un slo procesador, por lo tanto los hilos corren uno a la vez de forma tal que proveen la ilusin de concurrencia (esto es llamado scheduling). El sistema de ejecucin de Java soporta un algoritmo determinstico (para el scheduler) llamado fixed priority scheduling. Este algoritmo asigna tiempo de ejecucin a un hilo basado en su prioridad relativa a los dems hilos que estn listos para ejecutarse. Cuando se crea un nuevo hilo, hereda su prioridad del hilo que lo crea, sta puede ser modificada con el mtodo setPriority. Las prioridades son enteros entre MIN_PRIORITY y MAX_PRIORITY(constantes definidas en la clase Thread). Entre ms alto el entero, ms alta la prioridad. Si dos hilos con la misma prioridad estn esperando que el CPU los ejecute, el scheduler escoge uno utilizando round-robin (i.e. escoge uno aleatoriamente, se supone que round-robin ofrece iguales probabilidades de ejecucin a los hilos en cuestin). El hilo escogido para ejecucin, corre hasta que alguna de estas condiciones sea verdadera: y y y Un hilo con mayor prioridad est listo para ejecucin. El hilo cede su lugar (yields), o su mtodo run termina. En sistemas que soportan rebanadas de tiempo (time slicing), su tiempo asignado ha expirado. {

En ese momento el segundo hilo es atendido por el CPU y as sucesivamente hasta que el intrprete termina. El algoritmo del scheduler es preemptive. Si en cualquier momento un thred con mayor prioridad que los dems est listo para ser ejecutado, el sistema de ejecucin de Java lo escoge para ser ejecutado. Entonces decimos que el nuevo hilo (de mayor prioridad) desaloja (domina, toma la primera posicin, etc.) a los dems. La prioridad de los hilos debe ser utilizada slo para modificar la poltica de asignacin del scheduler (por cuestiones de eficiencia) y no para manejar la correccin de un programa. Esto debido a que el scheduler puede decidir ejecutar a un hilo con menor prioridad para evitar inanicin. Sincronizacin. Cuando tenemos varios hilos, muchas veces deseamos que stos pueden compartir datos, por lo tanto, es indispensable saber sincronizar sus actividades; esto tambin nos permitir evitar inanicin y abrazos mortales. En muchas situaciones, hilos que se ejecutan concurrentemente comparten informacin y deben considerar el estado de las actividades de los dems hilos. Un modelo muy comn de tales conjuntos de hilos es conocido como escenarios de productor/consumidor, donde el productor genera un flujo de datos que es consumido por un consumidor. Los segmentos de cdigo dentro de un programa que accesan el mismo objeto desde hilos separados (concurrentes) se llaman regiones crticas. En Java, una seccin crtica puede ser un bloque o un mtodo. Java provee algunos mtodos ms para coordinar las actividades de los hilos, como notifyAll, wait, etc. Agrupamientos de hilos. Todo hilo en Java es miembro de un grupo. Un grupo de hilos nos da las herramientas para meter varios hilos en un slo objeto y manipularlos (a todos) al mismo tiempo (a esto le llama: ``comodidad''). La clase ThreadGroup implementa los grupos de hilos en Java. El sistema de ejecucin de Java pone a un hilo en un grupo durante la construccin del hilo. Cuando se crea un hilo, uno puede escoger el grupo al que pertenecer o permitir que el sistema seleccione un grupo razonable por omisin para nuestro nuevo hilo. El hilo as creado es miembro permanente del grupo al cual se una durante su creacin -no puede ser cambiado. Si se crea un hilo sin especificar su grupo en el constructor, el sistema de ejecucin automticamente pone el nuevo hilo en el mismo grupo que el hilo que lo crea. Cuando una aplicacin de Java arranca, el sistema de ejecucin de Java crea un ThreadGroup llamado main. A menos que se especifique lo contrario, todos los nuevos hilos que se creen durante el desarrollo de la aplicacin sern miembros del grupo de hilos main. La clase Thread provee tres constructores que te permiten asignar a un grupo al hilo que ests creando. Finalmente la clase ThreadGroup provee un conjunto de mtodos que te permiten obtener informacin como: qu otros hilos pertenecen al mismo grupo, modificar los hilos por grupo: suspenderlos, activarlos, detenerlos, etc. todo con una sola invocacin a los mtodos respectivos. EJEMPLO consideramos ThreadGroup migrupo = new ThreadGroup(``Mi grupo de hilos''); Thread myhilo = new Thread(migrupo, ``Un hilo en mi grupo''); ... elgrupo = myhilo.getThreadGroup(); ...

Comunicacin entre hilos Java proporciona un mecanismo elegante de comunicacin entre procesos, a travs de los mtodos wait, notify y notifyAll. Estos mtodos se implementan como mtodos de final en Object, de manera que todas las clases disponen de ellos. Cualquiera de los tres mtodos slo puede ser llamado desde dentro de un mtodo synchronized. y y y wait: le indica al hilo en curso que abandone el monitor y se vaya a dormir hasta que otro hilo entre en el mismo monitor y llame a notify. notify: despierta al primer hilo que realiz una llamada a wait sobre el mismo objeto. notifyAll_: despierta todos los hilos que realizaron una llamada a wait sobre el mismo objeto. El hilo con mayor prioridad de los despertados es el primero en ejecutarse.

Un ejemplo que nos sirve es el de dos hilos uno productor de informacin y el otro consumidor que usan un espacio comun para comunicarse. El productor trata de producir informacin tan rpido como puede, mientras que el consumidor trata de consumir tan rpido como le es posible. class EspacioComun { int n; boolean valueSet = false; synchronized int get() { if (!valueSet) try { wait(); } catch(InterruptedException e){}; System.out.println("Obtenido: " + n); valueSet = false; notify(); return n; } synchronized void put(int n) { if (valueSet) try { wait(); } catch(InterruptedException e) {}; this.n = n; valueSet = true; System.out.println("Colocado: " + n); notify(); } } class Producer implements Runnable { EspacioComun miEspacio; Producer (EspacioComun miEspacio) { this.miEspacio = miEspacio; new Thread(this, "Producer").start(); } public void run() { int i = 0; while(true) { miEspacio.put(i++); } } } class Consumer implements Runnable { EspacioComun miEspacio; Consumer(EspacioComun miEspacio) { this.miEspacio = miEspacio; new Thread(this, "Consumer").start(); } public void run() { while(true) { miEspacio.get(); } }

} public class PC { public static void main(String args[]) { EspacioComun miEspacio = new EspacioComun(); new Producer(miEspacio); new Consumer(miEspacio); } }

Bloqueos Los bloqueos son condiciones anmalas inusuales, y muy difciles de depurar, donde dos hilos presentan una dependencia circular sobre un par de objetos sincronizados. Por ejemplo, si un hilo entra en el monitor sobre el objeto X y otro hilo entra en le monitor sobre el objeto Y, y si X intenta llamar a cualquier mtodo sincronizado sobre Y, tal y como cabe esperar quedar detenido. Sin embargo, si Y, por su parte, intenta llamar a cualquier mtodo sincronizado con X, entonces quedar esperando indefinidamente, ya que para conseguir el cerrojo de X tendra antes que liberar su propio cerrojo en Y, con el fin de que el primer hilo pudiera completarse. Podemos dividir los hilos en dos categoras: 1. Hilo de INTERFACE de usuario: Este tipo de hilo crea su propia ventana, y as recibe mensajes de ventana. Puede responder al usuario a travs de su propia ventana. Este tipo de hilo est sujeto a la regla del Mutex de Win16 que permite slo un hilo de interface de usuario en el ncleo de usuario y gdi de 16 bits. Mientras el hilo de interface de usuario est ejecutando cdigo de ncleo de usuario y gdi de 16 bits, otros hilos UI no podrn usar los servicios del ncleo de usuario y gdi. Se puede observar que este Mutex de Win16 es especfico a Windows 95 desde su interior, pues las funciones de la API de Windows 95 se remontan (thunk down) hasta el cdigo de 16 bits. Windows NT no tiene Mutex de Win16 as que los hilos de interfase de usuario bajo NT trabajan con ms fluidez que bajo Windows 95. 2. Hilo obrero (Worker thread): Este tipo de hilo no crea ninguna ventana as que no puede recibir ningn mensaje de ventana. Existe bsicamente para hacer la tarea asignada en el trasfondo hence el nombre del hilo obrero. COMO APLICAR LOS MULTIHILOS EN APPLETS: Lo primero es asegurarse que el applet implementa el interfaz Runnable, necesario para el soporte de threads, o hilos de ejecucin. Luego se declara un objeto de tipo Thread, es decir, hilo, y se iguala a null. En el mtodo start(), que es donde se encuentra todo el cdigo de inicializacin, se crea el hilo y se arranca llamando a su mtodo start(). En stop(), por el contrario, se detiene. a) Encabezado de todo applet: /** * Applet MostrarCadena * * * * */

b) Ubicacin de la interfaz Runnable, declaracin de variables e hilos: import java.awt.*; import java.applet.*; public class MostrarCadena extends Applet implements Runnable { String mensaje; int lugar; Thread hilo = null; public void init() { mensaje = getParameter("cadena"); if (mensaje==null) mensaje = "Ya casi terminamos Java"; lugar = getBounds().width; } public void start() { if (hilo==null) { hilo = new Thread(this); hilo.start(); } } public void stop() { hilo = null; } public void paint(Graphics g) { g.drawString(mensaje,lugar,20); } public void run() { while (hilo!=null && hilo.isAlive()) { lugar -= 1; repaint(); try { hilo.sleep(10); } catch (InterruptedException e) {} // No hacemos nada } } } El mtodo run() es nuevo y es consecuencia de la implementacin del interfaz Runnable. Cuando se crea un hilo de ejecucin, como se ha hecho en start(), el hilo recin creado siempre comienza su vida til ejecutando el mtodo run(). As pues, aqu estar el cdigo del hilo. Ahora se hace la pregunta si existe el hilo definido (hilo!=null) y si est ejecutndose (isAlive). Luego mueve el texto un poco a la izquierda, repinta, y se obliga a s mismo a dejar de ejecutarse durante 10 milisegundos por medio del mtodo sleep(). Transcurrido ese tiempo seguir su ejecucin por el mismo sitio donde la dej (por esta razn es necesario el while). Indicar por ltimo que es obligatorio capturar la excepcin InterruptedException para poder llamar al mtodo sleep(). En caso contrario el compilador avisa. As pues, se hace, aunque no se especifique ningn cdigo en caso de que se lance dicha excepcin. Esto ocurrir en casos muy excepcionales, por lo que no hay preocupacin alguna.

II.1. FUNDAMENTOS A. Introduccin Java es un lenguaje orientado a objetos, que se deriva en alto grado de C++, de tal forma que puede ser considerado como un C++ nuevo y modernizado o bien como un C++ al que se le han amputado elementos heredados del lenguaje estructurado C. B. Tokens Un token es el elemento ms pequeo de un programa que es significativo para el compilador. Estos tokens definen la estructura de Java. Cuando se compila un programa Java, el compilador analiza el texto, reconoce y elimina los espacios en blanco y comentarios y extrae tokens individuales. Los tokens resultantes se compilan, traducindolos a cdigo de byte Java, que es independiente del sistema e interpretable dentro de un entorno Java. Los cdigos de byte se ajustan al sistema de mquina virtual Java, que abstrae las diferencias entre procesadores a un procesador virtual nico. Los tokens Java pueden subdividirse en cinco categoras: Identificadores, palabras clave, constantes, operadores y separadores. a.) Identificadores Los identificadores son tokens que representan nombres asignables a variables, mtodos y clases para identificarlos de forma nica ante el compilador y darles nombres con sentido para el programador. Todos los identificadores de Java diferencian entre maysculas y minsculas (Java es Case Sensitive o Sensible a maysculas) y deben comenzar con una letra, un subrayado(_) o smbolo de dlar($). Los caracteres posteriores del identificador pueden incluir las cifras del 0 al 9. Como nombres de identificadores no se pueden usar palabras claves de Java. Adems de las restricciones mencionadas existen propuestas de estilo. Es una prctica estndar de Java denominar: y y y y y y Las clases: Clase o MiClase. Las interfaces: Interfaz o MiInterfaz. Los mtodos: metodo() o metodoLargo(). Las variables: altura o alturaMedia. Las constantes: CONSTATE o CONSTANTE_LARGA. Los paquetes: java.paquete.subpaquete.

Sin entrar en ms detalle en la siguiente lnea de cdigo se puede apreciar la declaracin de una variable entera (int) con su correspondiente identificador: int alturaMedia; b.) Palabras clave Las palabras claves son aquellos identificadores reservados por Java para un objetivo determinado y se usan slo de la forma limitada y especfica. Java tiene un conjunto de palabras clave ms rico que C o que C++, por lo que s est aprendiendo Java con conocimientos de C o C++, asegrese de que presta atencin a las palabras clave de Java.

Las siguientes palabras son palabras reservadas de Java: abstact case const else float if int null protected static throw var boolean cast continue extends for implements interface operator public super throws void break catch default false future import long outer rest switch transient volatile Tabla 2: Palabras reservadas Java Las palabras subrayadas son palabras reservadas pero no se utilizan. La definicin de estas palabras clave no se ha revelado, ni se tiene un calendario respecto a cundo estar alguna de ellas en la especificacin o en alguna de las implementaciones de Java. c.) Literales y constantes Los literales son sintaxis para asignar valores a las variables. Cada variables es de un tipo de datos concreto, y dichos tipos de datos tienen sus propios literales. Mediante determinados modificadores (static y final) podremos crear variables constantes, que no modifican su valor durante la ejecucin de un programa. Las constantes pueden ser numricas, booleanas, caracteres (Unicode) o cadenas (String). Las cadenas, que contienen mltiples caracteres, an se consideran constantes, aunque estn implementadas en Java como objetos. Veamos un ejemplo de constante declarada por el usuario: final static int ALTURA_MAXIMA = 200; Se puede observar que utilizamos final static, para que la variable sea total y absolutamente invariable. d.) Operadores Conocidos tambin como operandos, indican una evaluacin o computacin para ser realizada en objetos o datos, y en definitiva sobre identificadores o constantes. Los operadores admitidos por Java son: + >>>= &= == >> ! & ^ . > < = && / ] != ) %=

?!!

/= Tabla 3: Operadores Java

>>

As por ejemplo el siguiente fragmento de cdigo incrementa el valor de una variable en dos unidades, mediante la utilizacin del operador aritmtico + que se utiliza para la suma: int miNumero=0; miNumero = miNumero + 2; En el apartado "II.3 Operadores" de este tutorial aprenderemos que en Java hay formas ms sencillas de hacer esto mismo, y estudiaremos el significado de cada uno de estos operadores. e.) Separadores Se usan para informar al compilador de Java de cmo estn agrupadas las cosas en el cdigo. Los separadores admitidos por Java son: { } , : ; f.) Comentarios y espacios en blanco El compilador de Java reconoce y elimina los espacios en blanco, tabuladores, retornos de carro y comentarios durante el anlisis del cdigo fuente. Los comentarios se pueden presentar en tres formatos distintos: Formato /*comentario*/ //comentario /**comentario*/ Uso Se ignoran todos los caracteres entre /* */. Proviene del C Se ignoran todos los caracteres detrs de // hasta el fin de lnea. Proviene del C++ Lo mismo que /* */ pero se podrn utilizar para documentacin automtica. Tabla 4: Formatos de comentarios Java Por ejemplo la siguiente lnea de cdigo presenta un comentario: int alturaMinima = 150; // No menos de 150 centmetros C. Expresiones Los operadores, variables y las llamadas a mtodos pueden ser combinadas en secuencias conocidas como expresiones. El comportamiento real de un programa Java se logra a travs de expresiones, que se agrupan para crear sentencias. Una expresin es una serie de variables, operadores y llamadas a mtodos (construida conforme a la sintaxis del lenguaje) que se evala a un nico valor. Entre otras cosas, las expresiones son utilizadas para realizar clculos, para asignar valores a variables, y para ayudar a controlar la ejecucin del flujo del programa. La tarea de una expresin se compone de dos partes: realiza el clculo indicado por los elementos de la expresin y devuelve el valor obtenido como resultado del clculo. Los operadores devuelven un valor, por lo que el uso de un operador es una expresin. Por ejemplo, la siguiente sentencia es una expresin:

int contador=1; contador++; La expresin contador++ en este caso particular se evala al valor 1, que era el valor de la variable contador antes de que la operacin ocurra, pero la variable contador adquiere un valor de 2. El tipo de datos del valor devuelto por una expresin depende de los elementos utilizados en la expresin. La expresin contador++ devuelve un entero porque ++ devuelve un valor del mismo tipo que su operando ycontador es un entero. Otras expresiones devuelven valores booleanos, cadenas... Una expresin de llamada a un mtodo se evala al valor de retorno del mtodo; as el tipo de dato de la expresin de llamada a un mtodo es el mismo que el tipo de dato del valor de retorno de ese mtodo. Otra sentencia interesante sera: in.read( ) != -1 // in es un flujo de entrada Esta sentencia se compone de dos expresiones: 1. 2. La primera expresin es una llamada al mtodo in.read(). El mtodo in.read() ha sido declarado para devolver un entero, por lo que la expresin in.read() se evala a un entero. La segunda expresin contenida en la sentencia utiliza el operador !=, que comprueba si dos operandos son distintos. En la sentencia en cuestin, los operandos son in.read() y -1. El operando in.read() es vlido para el operador != porque in.read() es una expresin que se evala a un entero, as que la expresin in.read()!=-1 compara dos enteros. El valor devuelto por esta expresin ser verdadero o falso dependiendo del resultado de la lectura del fichero in.

Como se puede observar, Java permite construir sentencias (expresiones compuestas) a partir de varias expresiones ms pequeas con tal que los tipos de datos requeridos por una parte de la expresin concuerden con los tipos de datos de la otra. D. Bloques y mbito En Java el cdigo fuente est dividido en partes separadas por llaves, denominas bloques. Cada bloque existe independiente de lo que est fuera de l, agrupando en su interior sentencias (expresiones) relacionadas. Desde un bloque externo parece que todo lo que est dentro de llaves se ejecuta como una sentencia. Pero, qu es un bloque externo?. Esto tiene explicacin si entendemos que existe una jerarqua de bloques, y que un bloque puede contener uno o ms subbloques anidados. El concepto de mbito est estrechamente relacionado con el concepto de bloque y es muy importante cuando se trabaja con variables en Java. El mbito se refiere a cmo las secciones de un programa (bloques) afectan el tiempo de vida de las variables. Toda variable tiene un mbito, en el que es usada, que viene determinado por los bloques. Una variable definida en un bloque interno no es visible por el bloque externo. Las llaves de separacin son importantes no slo en un sentido lgico, ya que son la forma de que el compilador diferencie dnde acaba una seccin de cdigo y dnde comienza otra, sino que tienen una connotacin esttica que facilita la lectura de los programas al ser humano. As mismo, para identificar los diferentes bloques se utilizan sangras. Las sangras se utilizan para el programador, no para el compilador. La sangra (tambin denominada indentacin) ms adecuada para la esttica de un programa Java son dos espacios: {

// Bloque externo

int x = 1;

{

// Bloque interno invisible al exterior

int y = 2;

}

x = y; // Da error: Y fuera de mbito

} II.2. TIPOS DE DATOS A. Tipos de datos simples Es uno de los conceptos fundamentales de cualquier lenguaje de programacin. Estos definen los mtodos de almacenamiento disponibles para representar informacin, junto con la manera en que dicha informacin ha de ser interpretada. Para crear una variable (de un tipo simple) en memoria debe declararse indicando su tipo de variable y su identificador que la identificar de forma nica. La sintaxis de declaracin de variables es la siguiente: TipoSimple Identificador1, Identificador2; Esta sentencia indica al compilador que reserve memoria para dos variables del tipo simple TipoSimple con nombres Identificador1 e Identificador2. Los tipos de datos en Java pueden dividirse en dos categoras: simples y compuestos. Los simples son tipos nucleares que no se derivan de otros tipos, como los enteros, de coma flotante, booleanos y de carcter. Los tipos compuestos se basan en los tipos simples, e incluyen las cadenas, las matrices y tanto las clases como las interfaces, en general. Cada tipo de datos simple soporta un conjunto de literales que le pueden ser asignados, para darles valor. En este apartado se explican los tipos de datos simples (o primitivos) que presenta Java, as como los literales que soporta (sintaxis de los valores que se les puede asignar).

a.) Tipos de datos enteros Se usan para representar nmeros enteros con signo. Hay cuatro tipos: byte, short, int y long. Tipo byte short int long Tamao 1Byte (8 bits) 2 Bytes (16 bits) 4 Bytes (32 bits) 8 Bytes (64 bits)

Tabla 5: Tipos de datos enteros Literales enteros Son bsicos en la programacin en Java y presentan tres formatos: y y y Decimal: Los literales decimales aparecen como nmeros ordinarios sin ninguna notacin especial. Hexadecimal: Los hexadecimales (base 16) aparecen con un 0x 0X inicial, notacin similar a la utilizada en C y C++. Octal: Los octales aparecen con un 0 inicial delante de los dgitos.

Por ejemplo, un literal entero para el nmero decimal 12 se representa en Java como 12 en decimal, como 0xC en hexadecimal, y como 014 en octal. Los literales enteros se almacenan por defecto en el tipo int, (4 bytes con signo), o si se trabaja con nmeros muy grandes, con el tipo long, (8 bytes con signo), aadiendo una L l al final del nmero. La declaracin de variables enteras es muy sencilla. Un ejemplo de ello sera: long numeroLargo = 0xC; // Por defecto vale 12 b.) Tipos de datos en coma flotante Se usan para representar nmeros con partes fraccionarias. Hay dos tipos de coma flotante: float y double. El primero reserva almacenamiento para un nmero de precisin simple de 4 bytes y el segundo lo hace para un numero de precisin doble de 8 bytes. Tipo float double Tamao 4 Byte (32 bits) 8 Bytes (64 bits)

Tabla 6: Tipos de datos numricos en coma flotante Literales en coma flotante Representan nmeros decimales con partes fraccionarias. Pueden representarse con notacin estndar (563,84) o cientfica (5.6384e2). De forma predeterminada son del tipo double (8 bytes). Existe la opcin de usar un tipo ms corto (el tipo float de 4 bytes), especificndolo con una F f al final del nmero. La declaracin de variables de coma flotante es muy similar a la de las variables enteras. Por ejemplo: double miPi = 314.16e-2 ; // Aproximadamente float temperatura = (float)36.6; // Paciente sin fiebre

Se realiza un moldeado a temperatura, porque todos los literales con decimales por defecto se consideran double. c.) Tipo de datos boolean Se usa para almacenar variables que presenten dos estados, que sern representados por los valores true y false. Representan valores bi-estado, provenientes del denominado lgebra de Boole. Literales Booleanos Java utiliza dos palabras clave para los estados: true (para verdadero) y false (para falso). Este tipo de literales es nuevo respecto a C/C++, lenguajes en los que el valor de falso se representaba por un 0 numrico, y verdadero cualquier nmero que no fuese el 0. Para declarar un dato del tipo booleano se utiliza la palabra reservada boolean: boolean reciboPagado = false; // Aun no nos han pagado?! d.) Tipo de datos carcter Se usa para almacenar caracteres Unicode simples. Debido a que el conjunto de caracteres Unicode se compone de valores de 16 bits, el tipo de datos char se almacena en un entero sin signo de 16 bits. Java a diferencia de C/C++ distingue entre matrices de caracteres y cadenas. Literales carcter Representan un nico carcter (de la tabla de caracteres Unicode 1.1) y aparecen dentro de un par de comillas simples. De forma similar que en C/C++. Los caracteres especiales (de control y no imprimibles) se representan con una barra invertida ('\') seguida del cdigo carcter. Descripcin Caracter Unicode Numero octal Barra invertida Continuacin Retroceso Retorno de carro Alimentacin de formularios Tabulacin horizontal Lnea nueva Comillas simples Comillas dobles Nmeros arbigos ASCII Alfabeto ASCII en maysculas Alfabeto ASCII en minsculas Representacin \udddd \ddd \\ \ \b \r \f \t \n \ \" 0-9 A.-Z a.-z \u005C \ \u0008 \u000D \u000C \u0009 \u000A \u0027 \u0022 \u0030 a \u0039 \u0041 a \u005A \u0061 a \u007A Valor Unicode

Tabla 7: Caracteres especiales Java Las variables de tipo char se declaran de la siguiente forma: char letraMayuscula = 'A'; // Observe la necesidad de las ' '

char letraV = '\u0056'; // Letra 'V' e.) Conversin de tipos de datos En Java es posible transformar el tipo de una variable u objeto en otro diferente al original con el que fue declarado. Este proceso se denomina "conversin", "moldeado" o "tipado". La conversin se lleva a cabo colocando el tipo destino entre parntesis, a la izquierda del valor que queremos convertir de la forma siguiente: char c = (char)System.in.read(); La funcin read devuelve un valor int, que se convierte en un char debido a la conversin (char), y el valor resultante se almacena en la variable de tipo carcter c. El tamao de los tipos que queremos convertir es muy importante. No todos los tipos se convertirn de forma segura. Por ejemplo, al convertir un long en un int, el compilador corta los 32 bits superiores del long (de 64 bits), de forma que encajen en los 32 bits del int, con lo que si contienen informacin til, esta se perder. Por ello se establece la norma de que "en las conversiones el tipo destino siempre debe ser igual o mayor que el tipo fuente": Tipo Origen byte short char int long float Tipo Destino double, float, long, int, char, short double, float, long, int double, float, long, int double, float, long double, float double

Tabla 8: Conversiones sin prdidas de informacin B. Vectores y Matrices Una matriz es una construccin que proporciona almacenaje a una lista de elementos del mismo tipo, ya sea simple o compuesto. Si la matriz tiene solo una dimensin, se la denomina vector. En Java los vectores se declaran utilizando corchetes ( [ y ] ), tras la declaracin del tipo de datos que contendr el vector. Por ejemplo, esta sera la declaracin de un vector de nmeros enteros (int): int vectorNumeros[ ]; // Vector de nmeros Se observa la ausencia de un nmero que indique cuntos elementos componen el vector, debido a que Java no deja indicar el tamao de un vector vaco cuando le declara. La asignacin de memoria al vector se realiza de forma explcita en algn momento del programa. Para ello o se utiliza el operador new: int vectorNumeros = new int[ 5 ]; // Vector de 5 nmeros O se asigna una lista de elementos al vector: int vectorIni = { 2, 5, 8}; // == int vectorIni[3]=new int[3]; Se puede observar que los corchetes son opcionales en este tipo de declaracin de vector, tanto despus del tipo de variable como despus del identificador.

Si se utiliza la forma de new se establecer el valor 0 a cada uno de los elementos del vector. C. Cadenas En Java se tratan como una clase especial llamada String. Las cadenas se gestionan internamente por medio de una instancia de la clase String. Una instancia de la clase String es un objeto que ha sido creado siguiendo la descripcin de la clase. Cadenas constantes Representan mltiples caracteres y aparecen dentro de un par de comillas dobles. Se implementan en Java con la clase String. Esta representacin es muy diferente de la de C/C++ de cadenas como una matriz de caracteres. Cuando Java encuentra una constante de cadena, crea un caso de la clase String y define su estado, con los caracteres que aparecen dentro de las comillas dobles. Vemos un ejemplo de cadena declarada con la clase String de Java: String capitalUSA = "Washington D.C."; String nombreBonito = "Amelia"; Ms tarde profundizaremos con detenimiento en las cadenas Java. II.3. OPERADORES A. Introduccin Los operadores son un tipo de tokens que indican una evaluacin o computacin para ser realizada en objetos o datos, y en definitiva sobre identificadores o constantes. Adems de realizar la operacin, un operador devuelve un valor, ya que son parte fundamental de las expresiones. El valor y tipo que devuelve depende del operador y del tipo de sus operandos. Por ejemplo, los operadores aritmticos devuelven un nmero como resultado de su operacin. Los operadores realizan alguna funcin sobre uno, dos o tres operandos. Los operadores que requieren un operando son llamados operadores unarios. Por ejemplo, el operador "++" es un operador unario que incrementa el valor de su operando en una unidad. Los operadores unarios en Java pueden utilizar tanto la notacin prefija como la posfija. La notacin prefija indica que el operador aparece antes que su operando. ++contador // Notacin prefija, se evala a: contador+1 La notacin posfija indica que el operador aparece despus de su operando: contador++ // Notacin posfija, se evala a: contador Los operadores que requieren dos operandos se llaman operadores binarios. Por ejemplo el operador "=" es un operador binario que asigna el valor del operando del lado derecho al operando del lado izquierdo. Todas los operadores binarios en Java utilizan notacin infija, lo cual indica que el operador aparece entre sus operandos. operando1 operador operando2

Por ltimo, los operadores ternarios son aquellos que requieren tres operandos. El lenguaje Java tiene el operador ternario, "?":, que es una sentencia similar a la if-else. Este operador ternario usa notacin infija; y cada parte del operador aparece entre operandos: expresin ? operacin1 : operacin2 Los operadores de Java se pueden dividir en las siguientes cuatro categoras: y y y y Aritmticos. De comparacin y condicionales. A nivel de bits y lgicos. De asignacin.

B. Operadores aritmticos El lenguaje Java soporta varios operadores aritmticos para los nmeros enteros y en coma flotante. Se incluye + (suma), (resta), * (multiplicacin), / (divisin), y % (mdulo, es decir, resto de una divisin entera). Por ejemplo: sumaEste + aEste; //Suma los dos enteros divideEste % entreEste; //Calcula el resto de dividir 2 enteros Operador + * / % Uso op1 + op2 op1 - op2 op1 * op2 op1 / op2 op1 % op2 Descripcin Suma op1 y op2 Resta op2 de op1 Multiplica op1 por op2 Divide op1 por op2 Calcula el resto de dividir op1 entre op2

Tabla 9: Operadores aritmticos binarios de Java El tipo de los datos devueltos por una operacin aritmtica depende del tipo de sus operandos; si se suman dos enteros, se obtiene un entero como tipo devuelto con el valor de la suma de los dos enteros. Estos operadores se deben utilizar con operandos del mismo tipo, o si no realizar una conversin de tipos de uno de los dos operandos al tipo del otro. El lenguaje Java sobrecarga la definicin del operador + para incluir la concatenacin de cadenas. El siguiente ejemplo utiliza + para concatenar la cadena "Contados ", con el valor de la variable contador y la cadena "caracteres.": System.out.print("Contados" + contador + "caracteres."); Esta operacin automticamente convierte el valor de contador a una cadena de caracteres. Los operadores + y - tienen versiones unarias que realizan las siguientes operaciones: Operador + Uso +op -op Descripcin Convierte op a entero si es un byte, short o char Niega aritmticamente op

Tabla 10: Versiones unarias de los operadores "+" y "-" El operador - realiza una negacin del nmero en complemento A2, es decir, cambiando de valor todos sus bits y sumando 1 al resultado final:

42 -> 00101010

-42 -> 11010110

Existen dos operadores aritmticos que funcionan como atajo de la combinacin de otros: ++ que incrementa su operando en 1, y -que decrementa su operando en 1. Ambos operadores tienen una versin prefija, y otra posfija. La utilizacin la correcta es crtica en situaciones donde el valor de la sentencia es utilizado en mitad de un clculo ms complejo, por ejemplo para control de flujos: Operador ++ ++ --Uso op++ ++op op---op Descripcin Incrementa op en 1; se evala al valor anterior al incremento Incrementa op en 1; se evala al valor posterior al incremento Decrementa op en 1; se evala al valor anterior al incremento Decrementa op en 1; se evala al valor posterior al incremento Tabla 11: Operaciones con "++" y "--" C. Operadores de comparacin y condicionales Un operador de comparacin compara dos valores y determina la relacin existente entre ambos. Por ejemplo, el operador != devuelve verdadero (true) si los dos operandos son distintos. La siguiente tabla resume los operadores de comparacin de Java: Operador > >= < op2 op1 >= op2 op1 < op2 op1 >> Uso op1 >> op2 op1 >> op2 Operacin Desplaza los bits de op1 a la derecha op2 veces Desplaza los bits de op1 a la izquierda op2 veces Desplaza los bits de op1 a la derecha op2 veces (sin signo)

Tabla 14: Operadores de desplazamiento de bits Los tres operadores de desplazamiento simplemente desplazan los bits del operando de la parte izquierda el nmero de veces indicado por el operando de la parte derecha. El desplazamiento ocurre en la direccin indicada por el operador. Por ejemplo, la siguiente sentencia, desplaza los bits del entero 13 a la derecha una posicin: 13 >> 1; La representacin en binario del nmero 13 es 1101. El resultado de la operacin de desplazamiento es 1101 desplazado una posicin a la derecha, 110 o 6 en decimal. Se debe tener en cuenta que el bit ms a la derecha se pierde en este caso. Un desplazamiento a la derecha una posicin es equivalente a dividir el operando del lado izquierdo por 2, mientras que un desplazamiento a la izquierda de una posicin equivale a multiplicar por 2, pero un desplazamiento es ms eficiente, computacionalmente hablando, que una divisin o multiplicacin. El desplazamiento sin signo >>> funciona de la siguiente manera: y y Si se desplaza con signo el nmero -1 (1111), seguir valiendo -1, dado que la extensin de signo sigue introduciendo unos en los bits ms significativos. Con el desplazamiento sin signo se consigue introducir ceros por la izquierda, obteniendo el nmero 7 (0111).

Este tipo de desplazamientos es especialmente til en la utilizacin de mscaras grficas. b.) Operadores de lgica de bits La lgica de bits (lgica de Bool) se utiliza para modelizar condiciones biestado y trabajar con ellas (cierto/falso, true/false, 1/0).

En Java hay cuatro operadores de lgica de bits: Operador & | ^ ~ Uso op1 & op2 op1 | op2 op1 ^ op2 ~op2 Operacin AND OR OR Exclusivo Complemento

Tabla 15: Operadores de lgica de bits El operador & realiza la operacin AND de bit. Aplica la funcin AND sobre cada par de bits de igual peso de cada operando. La funcin AND es evaluada a cierto si ambos operandos son ciertos. Por ejemplo vamos a aplicar la operacin AND a los valores 12 y 13: 12 & 13 El resultado de esta operacin es 12. Por qu?. La representacin en binario de 12 es 1100, y de 13 es 1101. La funcin AND pone el bit de resultado a uno si los dos bits de los operandos son 1, sino, el bit de resultado es 0: 1101 & 1100 -----1100

El operador | realiza la operacin OR de bit. Aplica la funcin OR sobre cada par de bits de igual peso de cada operando. La funcin OR es evaluada a cierto si alguno de los operandos es cierto. El operador ^ realiza la operacin OR exclusivo de bit (XOR). Aplica la funcin XOR sobre cada par de bits de igual peso de cada operando. La funcin XOR es evaluada a cierto si los operandos tienen el mismo valor. Para finalizar, el operador de complemento invierte el valor de cada bit del operando. Convierte el falso en cierto, y el cierto en falso: Entre otras cosas, la manipulacin bit es til para gestionar indicadores booleanos (banderas). Supongamos, por ejemplo, que se tiene varios indicadores booleanos en nuestro programa, los cuales muestran el estado de varios componentes del programa: esVisible, esArrastrable, etc... En lugar de definir una variable booleana para cada indicador, se puede definir una nica variable para todos ellos. Cada bit de dicha variable representar el estado vigente de uno de los indicadores. Se debern utilizar entonces manipulaciones de bit para establecer y leer cada indicador. Primero, se deben preparar las constantes de cada indicador. Esos indicadores deben ser diferentes unos de otros (en sus bits) para asegurar que el bit de activacin no se solape con otro indicador. Despus se debe definir la variable de banderas, cuyos bits deben de poder ser configurados segn el estado vigente en cada indicador. El siguiente ejemplo inicia la variable de banderas flags a 0, lo que significa que todos los indicadores estn desactivados (ninguno de los bits es 1): final int VISIBLE = 1; final int ARRASTRABLE = 2; final int SELECCIONABLE = 4;

final int MODIFICABLE = 8; int flags = 0; Para activar el indicador VISIBLE, se deber usar la sentencia: flags = flags | VISIBLE; Para comprobar la visibilidad se deber usar la sentencia: if ( (flags & VISIBLE) == 1 )

//Lo que haya que hacer

E. Operadores de asignacin El operador de asignacin bsico es el =, que se utiliza para asignar un valor a otro. Por ejemplo: int contador = 0; Inicia la variable contador con un valor 0. Java adems proporciona varios operadores de asignacin que permiten realizar un atajo en la escritura de cdigo. Permiten realizar operaciones aritmticas, lgicas, de bit y de asignacin con un nico operador. Supongamos que necesitamos sumar un nmero a una variable y almacenar el resultado en la misma variable, como a continuacin: i = i + 2; Se puede abreviar esta sentencia con el operador de atajo +=, de la siguiente manera: i += 2; La siguiente tabla muestra los operadores de atajo de asignacin y sus equivalentes largos: Operador += -= *= /= %= &= Uso op1 += op2 op1 -= op2 op1 *= op2 op1 /= op2 op1 %= op2 op1 &= op2 Equivalente a op1 = op1 + op2 op1 = op1 - op2 op1 = op1 * op2 op1 = op1 / op2 op1 = op1 % op2 op1 = op1 & op2

Tabla 16: Operadores de atajo de asignacin F. Precedencia de operadores Cuando en una sentencia aparecen varios operadores el compilador deber de elegir en qu orden aplica los operadores. A esto se le llama precedencia. Los operadores con mayor precedencia son evaluados antes que los operadores con una precedencia relativa menor. Cuando en una sentencia aparecen operadores con la misma precedencia:

y y

Los operadores de asignacin son evaluados de derecha a izquierda. Los operadores binarios, (menos los de asignacin) son evaluados de izquierda a derecha.

Se puede indicar explcitamente al compilador de Java cmo se desea que se evale la expresin con parntesis balanceados ( ). Para hacer que el cdigo sea ms fcil de leer y mantener, es preferible ser explcito e indicar con parntesis que operadores deben ser evaluados primero. La siguiente tabla muestra la precedencia asignada a los operadores de Java. Los operadores de la tabla estn listados en orden de precedencia: cuanto ms arriba aparezca un operador, mayor es su precedencia. Los operadores en la misma lnea tienen la misma precedencia: Tipo de operadores Operadores posfijos Operadores unarios Creacin o conversin Multiplicacin Suma Desplazamiento Comparacin Igualdad AND a nivel de bit OR a nivel de bit XOR a nivel de bit AND lgico OR lgico Condicional Asignacin Operadores de este tipo [ ] . (parametros) expr++ expr-++expr --expr +expr -expr ~ ! new (tipo) expr */% +