MAQUINA VIRTUAL DE JAVA Si se desea distribuir un programa escrito en un lenguaje tradicional como Visual Basic. Después de escribir el programa fuente necesitamos compilarlos en archivos de código objeto (.obj) y después enlazar dichos archivos para producir un ejecutable (.exe). Este ejecutable, además de tener todos el código objeto unido, tiene un encabezado para darle al sistema operativo información sobre como debe se ejecutado el archivo . Este ejecutable seria el que distribuiríamos. Este programa solo podría ejecutarse en computadoras con el sistema operativo para el cual fue desarrollado. Otros sistemas operativos no sabrían el formato del encabezado además que no pudieran ejecutar las llamadas al sistema y ni siquiera tendrían las librerías necesarias (como los DLL.). Aunque tuvieran las librerías de todos modos ni siquiera sabrían como correrlas! Como podría hacer que mi programa corra en diferentes plataformas (diferentes sistemas operativos corriendo sobre diferente hardware)? Una solución programar la aplicación en un lenguaje que sea soportable por varios sistemas operativos. Un problema que surge aquí es que necesitaría distribuir el código fuente (que no siempre es deseable). Otro problema que surge es que en cada sistema operativo las llamadas al sistema serian diferentes. Por lo que se tendrían que hacer adaptaciones al programa cada vez que se quisiera que fuera soportado por una nueva plataforma. La solución que propone Java es que el programa no corra sobre el hardware real, sino que corra sobre una maquina virtual. Es decir, dicha maquina no existe sino que es simulada por medio de software. Cada plataforma tendría instalada esta maquina virtual (que es un programa) y a la hora de correr los programas esta maquina virtual los correría. el cual va leyendo el programa y ejecutándolo instrucción por instrucción sobre el hardware real. A la maquina virtual de Java se le llama Java Virtual Machine (JVM). Los programas fuente de Java ( .java) al compilarse producirían unHconstituido de las instrucciones de la maquina virtual (java byte codes). La maquina virtual ya incluye un set de librerías para las llamadas al sistema. 1. Ventajas: a. Programas portables a cualquier plataforma (que cuente como una JVM). b. Diseño simple por no tener que ser backward compatible con nadie (que no era el caso de C++, ya que este tenia que ser backward compatible con C). c. Completamente orientado a objetos y con soporte de multithreading. d. Ideal para Internet por producir programas pequeños 2. Desventajas: a. Corre significativamente mas despacio que si corriera en hardware real. b. Hay que aprender un lenguaje nuevo. Notas: i. System es un objeto que se refiere al sistema en donde esta corriendo el programa. ii. out es el objeto de salida, es equivalente al flujo de salida cout de C++. iii. El nombre del archivo necesita tener el mismo nombre que la clase con extension .java (HelloApp.java) c. Applet d. e. f. g. h. i. j. k. l. import java.applet.Applet; import java.awt.*; class HelloApp extends Applet { public void paint (Graphics g) { g.drawString ("Hello world !", 0, 20); } } Para ejecutar el programa se tiene que hacer referencia a el desde una pagina para ser ejecutado por el browser. <HTML> <HEAD> <TITLE>Hello world</TITLE> </HEAD> <BODY> <APPLET CODE="HelloApp.class" WIDTH=250 HEIGHT=100> </APPLET> </BODY> </HTML> Nota: El comando Applet dentro del HTML le dice al browser a crear, posisionar y dimensionar la ventana de applet. Tambien asocia al applet con la ventana. Sin embargo el browser no tiene ni idea de que poner en la ventana. Lo que hace el browser es llamar al metodo paint(Graphics) cada vez que desee que se despliegue el contenido de la ventana (la primera vez y cada vez que quiere re desplegar el contenido). MULTIPLATAFORMAS DE JAVA 1. Supongamos que nosotros deseamos distribuir un programa escrito en un lenguaje tradicional como Visual Basic. Después de escribir el programa fuente (.frm, .bas por ej) necesitamos compilarlos en archivos de código objeto (.obj) y despues enlazar dichos archivos para producir un ejecutable (.exe). Este ejecutable, ademas de tener todos el código objeto unido, tiene un encabezado para darle al sistema operativo información sobre como debe se ejecutado el archivo (por ej. cuanta memoria necesita). Este ejecutable seria el que distribuiríamos. El problema es que tenemos muchas limitaciones. Este programa solo podria ejecutarse en computadoras con el sistema operativo para el cual fue desarrollado. Otros sistemas operativos (aunque estuvieran corriendo sobre la misma arquitectura del computador) no sabrian el formato del encabezado ademas que no pudieran ejecutar las llamadas al sistema y ni siquiera tendrian las librerias necesarias (como los .dll). Aunque tuvieran las librerias de todos modos ni siquiera sabrian como correrlas! Como podria hacer que mi programa corra en diferentes plataformas (diferentes sistemas operativos corriendo sobre diferente hardware)? Una solucion programar la aplicacion en un lenguaje que sea soportable por varios sistemas operativos. Un problema que surge aqui es que necesitaria distribuir el codigo fuente (que no siempre es deseable). Otro problema que surge es que en cada sistema operativo las llamadas al sistema serian diferentes. Por lo que se tendrian que hacer adaptaciones al programa cada vez que se quisiera que fuera soportado por una nueva plataforma. TIPOS DE DATOS PRIMITIVOS, VARIABLES Y LITERALES Valores primitivos: Números (42, 3.14159), String de texto ("hola !"), Lógicos (true, false) y especiales (null, undefined) Conversiones: operación + entre números y string convierte el numero a string y agrega. TIPOS DE DATOS PRIMITIVOS Java requiere que todas las variables tengan un tipo antes de que se puedan usar en un programa. Por esta razón, se dice que Java es un lenguaje de tipos estrictos. Los tipos de datos se dividen en cuatro categorías : Categorías Tipos de Datos primitivos Lógicos boolean Texto char Enteros byte, short, int y long Punto flotante double y float Dando un total de ocho tipos de datos primitivos: Tipo bits rango boolean 1 true o false Char 16 carácter de Unicode de ´\u0000´ a ´\uFFFF´ Byte 8 entero con signo de -128 a +127 Short 16 entero con signo de -32768 a +32767 int entero con signo de -2,147,483,648 a +2,147,483,647 32 long 64 entero con signo de -9,223,372,036,854,775,808 a +9,223,372,036,854,775,807 float 32 punto flotante de -3.40292347E+38 a +3.40292347E+38 double 64 punto flotante de -1,79769313486231570E+308 a +1,79769313486231570E+308 Cada uno de los tipos de datos de la tabla anterior se lista junto con su tamaño de bits (cada byte tiene 8 bits) y su intervalo de valores. Como los diseñadores de Java querían que fuera portátil, decidieron utilizar estándares internacionalmente reconocidos para los formatos tanto de caracteres (Unicode) como de números de punto flotante (IEEE754). OPERADORES ARITMÉTICOS Las expresiones son la forma más sencilla de un enunciado en JAva, es decir son enunciados que regresan un valor. Los operadores son símbolos especiales que, por lo general, se utilizan en expresiones. Operadores Ariméticos Operación Símbolo Expresión en Java suma + f+7 resta a-c - multiplicación * a*c división / w/t residuo% r%s Operadores de Igualdad y Relación = == x == y != x != y > > x>y < < x<y >= x >= y <= x <= y Operadores lógicos AND && (sexo== 1 ) &&(edad >=30) OR || (prom > 78 ) || (final == 80) NOT ! !(valor == 50) Una constante o una variable es una expresión por sí misma, así como las combinaciones de constantes con variables mediante operadores. Una expresión seguida de un punto y coma es una instrucción simple. Los operadores pueden se operadores binarios y operadores unarios. En el primer caso como su nombre lo dice intervienen dos variables que son conectadas por un operador. Por ejemplo Java proporciona varios operadores aritméticos entre los que se encuenteran =, +=, -=, *= y /=. Ejemplo : /** * La clase "PruebaOperadores" implementa una aplicación que * ilustra los operadores básicos. * La salida es la siguiente: * 12 8 6 * 686 * 6 8 14 * 22 8 14 * 24 10 33 * a/b = 1 * a%b=2 */ class PruebaOperadores { public static void main (String[] args) { int a = 12, b = 8, c = 6; System.out.println (a+" "+b+" "+c); a = c; System.out.println (a+" "+b+" "+c); c += b; System.out.println (a+" "+b+" "+c); a = b + c; System.out.println (a+" "+b+" "+c); a ++; ++b; c = a++ + ++b; System.out.println (a+" "+b+" "+" "+c); a = 6; b = 4; System.out.println ("a/b = "+a/b); System.out.println ("a % b = "+a % b); } } DATOS NUMÉRICOS El tipo numérico es el conjunto de los valores numéricos. Estos pueden representarse en dos formas distintas: Tipo numérico entero El tipo entero es un subconjunto finito de los númeron enteros. Los enteros son números completos, no tienen componentes fraccionarios o decimales y pueden ser negativos o positivos. Ejemplos de números enteros son: Números Enteros 5 6 -15 14 -20 26 Tipo numérico real El tipo real consiste en un subconjunto de los números reales. los números reales siempre tienen un número decimal y pueden ser positivos o negativos. Un número real consta de un entero y una parte decimal. Ejemplos de números reales son: Números Reales 0.08 3739.41 3.7452 -52.321 -8.12 3.0 DATOS LÓGICOS (BOOLEANOS) Ell tipo lógico _también denominado boléanos_ es aquel dato que sólo puede tomar uno de dos valores: Cierto o verdadero (true) y Falso (false). Este tipo de datos se utiliza para representar las alternativas (si/no) a determinadas condiciones. Por ejemplo, cuando se pide si un valor entero es par, la respuesta será verdadera o falsa, según sea par o impar. DATOS TIPO CARÁCTER El tipo Carácter es el conjunto finito y ordenado de caracteres que la computadora reconoce. Un dato tipo carácter contiene un sólo carácter. Los caracteres que reconocen las diferentes computadoras no son estándar, sin embargo, la mayoría reconoce los siguientes caracteres alfabéticos y numéricos: Caracteres alfabéticos (A, B, C, ...) Caracteres numéricos (1, 2, 3, 4, ...) Caracteres especiales (+, -, *, /, ., ;, >, <, ..., etc). Una modalidad de los datos carácter son el tipo Cadena los cuales están formados por una sucesión de caracteres que se encuentran delimitados por una comilla (apóstrofo) o dobles comillas, según el tipo de lenguaje de programación. La longitud de una cadena de caracteres es el número de ellos comprendidos entre los separadores o delimitadores. Por ejemplo: La cadena "curso" tiene una longitud de 5 caracteres. Mientras que la cadena " " tiene una longitud de un caracter que es un espacio. La cadena "" es una cadena vacía. La cadena "win-95" tiene una longitud de 6 elementos alfanuméricos. CLASES Una clase es una agrupación de datos y de código que actua sobre esos datos, a la que se le da un nombre. Una clase contiene: Datos (se denominan Datos Miembro). Estos pueden ser de tipos primitivos o referencias. Métodos (se denominan Métodos Miembro). La sintaxis general para la declaración de una clase es: modificadores class nombre_clase { declaraciones_de_miembros ; } Por ejemplo: class Punto { int x; int y; } Tipos de Clases Hasta ahora sólo se ha utilizado la palabra clave public para calificar el nombre de las clases que hemos visto, pero hay tres modificadores más. Los tipos de clases que podemos definir son: abstract Una clase abstract tiene al menos un método abstracto. Una clase abstracta no se instancia, sino que se utiliza como clase base para la herencia. final Una clase final se declara como la clase que termina una cadena de herencia. No se puede heredar de una clase final. Por ejemplo, la clase Math es una clase final. public Las clases public son accesibles desde otras clases, bien sea directamente o por herencia. Son accesibles dentro del mismo paquete en el que se han declarado. Para acceder desde otros paquetes, primero tienen que ser importadas. synchronizable Este modificador especifica que todos los métodos definidos en la clase son sincronizados, es decir, que no se puede acceder al mismo tiempo a ellos desde distintos threads; el sistema se encarga de colocar los flags necesarios para evitarlo. Este mecanismo hace que desde threads diferentes se puedan modificar las mismas variables sin que haya problemas de que se sobreescriban. OBJETO Cuando se crea un objeto (se instancia una clase) es posible definir un proceso de inicialización que prepare el objeto para ser usado. Esta inicialización se lleva a cabo invocando un método especial denominado constructor. Esta invocación es implícita y se realiza automáticamente cuando se utiliza el operador new. Los constructores tienen algunas características especiales: El nombre del constructor tiene que se igual al de la clase. Puede recibir cualquier número de argumentos de cualquier tipo, como cualquier otro método. No devuelve ningún valor (en su declaración no se declara ni siquiera void). El constructor no es un miembro más de una clase. Sólo es invocado cuando se crea el objeto (con el operador new). No puede invocarse explicitamente en ningún otro momento. Continuando con los ejemplos del capítulo anterior se podría escribir un constructor para la clase Punto, de la siguiente forma: class Punto { int x , y ; Punto ( int a , int b ) { x=a;y=b; } } Con este constructor se crearía un objeto de la clase Punto de la siguiente forma: Punto p = new Punto ( 1 , 2 ); CONSTRUCTORES Todas las clases Java tienen métodos especiales llamados Constructores que se utilizan para inicializar un objeto nuevo de ese tipo. Los contructores tienen el mismo nombre que la clase --el nombre del constructor de la clase Rectangle es Rectangle(), el nombre del constructor de la clase Thread es Thread(), etc... Java soporta la sobrecarga de los nombres de métodos para que una clase puede tener cualquier número de constructores, todos los cuales tienen el mismo nombre. Al igual que otros métodos sobrecargados, los constructores se diferencian unos de otros en el número y tipo de sus argumentos. Consideremos la clase Rectangle del paquete java.awt que proporciona varios constructores diferentes, todos llamados Rectangle(), pero cada uno con número o tipo diferentes de argumentos a partir de los cuales se puede crear un nuevo objeto Rectangle. Aquí tiene las firmas de los constructores de la clase java.awt.Rectangle: public Rectangle() public Rectangle(int width, int height) public Rectangle(int x, int y, int width, int height) public Rectangle(Dimension size) public Rectangle(Point location) public Rectangle(Point location, Dimension size) SOBRECARGA DE MÉTODOS Una misma clase puede tener varios métodos con el mismo nombre siempre que se diferencien en el tipo o número de los argurmentos. Cuando esto sucede se dice que el método está sobrecargado. Sin embargo no se puede sobrecargar cambiando sólo el tipo del valor devuelto. Por ejemplo: int metodoSobrecargado() { . . .} void metodoSobrecargado() { . . .} // error en compilación con esta definición, en la expresión y.metodoSobrecargado() la JVM no sabría que método invocar. Se puede sobrecargar cualquier método miembro de una clase, así como el constructor. INTERFACE Un interface es una colección de declaraciones de métodos (sin definirlos) y también puede incluir constantes. Runnable es un ejemplo de interface en el cual se declara, pero no se implemementa, una función miembro run. public interface Runnable { public abstract void run(); } Las clases que implementen (implements) el interface Runnable han de definir obligatoriamente la función run. class Animacion implements Runnable{ //.. public void run(){ //define la función run } } El papel del interface es el de describir algunas de las características de una clase. Por ejemplo, el hecho de que una persona sea un futbolista no define su personalidad completa, pero hace que tenga ciertas características que las distinguen de otras. Clases que no están relacionadas pueden implementar el interface Runnable, por ejemplo, una clase que describa una animación, y también puede implementar el interface Runnable una clase que realice un cálculo intensivo. POLIMORFISMO. Es el concepto de la orientación a objetos que permite invocar a un método independientemente de la clase a la que pertenezca un objeto, que puede conocerse recién en tiempo de ejecución. Gracias al polimorfismo, el objeto es el que recoge la llamada e invoca al método correspondiente, en forma dinámica. El polimorfismo permite mltiples implementaciones de métodos, dependiendo del tipo de objeto que se indica al invocar el método correspondiente. De esta manera el polimorfismo permite que el mismo mensaje enviado a diferentes objetos resulte en acciones dependientes del objeto que recibe el mensaje. Ejemplo: class Perro extends Mamifero { int numero_patas; public void mover() { System.out.println("Ahora es un perro el que se mueve"); } } public class Polimorfismo { public static void muevete(Mamifero m) { m.mover(); } public static void main(String[] args) { Gato bisho = new Gato(); Perro feo = new Perro(); muevete(bisho); muevete(feo); } }