Programación Orientada a Objetos Tema 2. Introducción al lenguaje Java
Resumen Introducción al lenguaje Java Origen de lenguaje y características generales Bytecode y máquina virtual Entornos de desarrollo: JDK, JRE, IDEs Desarrollo y ejecución de aplicaciones Ediciones de Java Elementos y sintaxis del lenguaje Java Creación de un programa Comentarios, identificadores y palabras reservadas Tipos primitivos, variables y constantes Operadores y expresiones básicas Control del flujo: if-else , switch-case, while , do- while , for Programación Orientada a Objetos
Introducción al lenguaje Java Programación Orientada a Objetos
Introducción al lenguaje Java Lenguajes compilables vs interpretables Lenguajes compilables A partir del código fuente, el compilador genera código máquina en forma de ficheros ejecutables que posteriormente pueden ejecutarse en la máquina particular. El compilador depende de la máquina: genera código sólo válido para un tipo de máquina particular. Cambiar de máquina conlleva volver a compilar. La ejecución es rápida una vez compilado. Ejemplos: lenguajes de alto nivel como C, Pascal, Ada, C++,...
Introducción al lenguaje Java Lenguajes compilables vs interpretables Lenguajes interpretables El intérprete no genera código máquina, sino que, a partir del código fuente efectúa la traducción y ejecución simultáneamente. La ejecución es más lenta que en lenguajes compilables . Ejemplos: algunos lenguajes de alto nivel como Basic y Matlab.
Bytecode y la máquina virtual de Java Java es un lenguaje interpretado por la máquina virtual de Java , que interpreta aplicaciones de Java compiladas a bytecode (ficheros . class ). El bytecode Java es independiente de la plataforma: puede ejecutarse en cualquier máquina virtual Java (JVM) sin importar la arquitectura de la computadora subyacente. compilador intérprete
Java es un lenguaje interpretado: El compilador genera bytecodes , que es un código neutro independiente de la plataforma (ficheros .class) La JVM ( Java Virtual Machine o Máquina Virtual de Java ) interpreta el código neutro (bytecodes) y lo convierte al código particular de la CPU utilizada y lo ejecuta. Los programas en java funcionan en todas las máquinas: al cambiar de máquina sólo cambia la JVM que hay que instalar. No hay que volver a compilar al cambiar de máquina. Bytecode y la máquina virtual de Java
Origen de Java Java surgió en 1991 por Sun MicroSystems y se comercializó por primera vez en 1995. Entre diciembre de 2006 y mayo de 2007, Sun Microsystems liberó la mayor parte de sus tecnologías Java bajo la licencia GNU GPL, de tal forma que prácticamente todo el Java de Sun es ahora software libre. Actualmente Sun pertenece al grupo Oracle, por lo que Java está en los dominios de Oracle. Motivación: distintos tipos de CPUs y continuos cambios motivó crear un lenguaje indepe ndiente del tipo de CPU ( lenguaje multiplataforma ).
Características de Java Orientado a Objetos (herencia y polimorfismo) Fácil de usar: No hay herencia múltiple de clases. Liberación automática de memoria: " Garbage collection “. Robusto: Lenguaje estrictamente tipado , comprueba el código en tiempo de compilación y de ejecución. Control de excepciones (permite controlar todo tipo de posibles errores p.e., división por cero, fichero no encontrado…). Programación Orientada a Objetos
Características de Java Seguro: Tiene mecanismos que evitan dañar la integridad del sistema cliente en aplicaciones en entornos de red o distribuidos. Arquitectura neutral (portable): Bytecodes generados son neutros, es decir, independientes de la plataforma. Interpretado: Los bytecodes son interpretados por la Máquina Virtual de Java dependiente de la plataforma. Dinámico: Las librerías pueden extenderse sin afectar a los clientes Programación Orientada a Objetos
Características de Java Multiproceso: Permite programas que ejecutan tareas a la vez usando hilos o threads Distribuido: Objetos situados en ordenadores diferentes pueden ejecutar procedimientos remotos (paquete). Inconvenientes: En algunos casos, la velocidad es menor frente a programas compilados. Programación Orientada a Objetos
Entornos de desarrollo - JDK Java Development Kit (JDK): conjunto de programas y librerías para desarrollar, compilar y ejecutar programas en Java desde consola. Contiene: javac.exe : Compilador de Java. Transforma el código fuente (.java ) en bytecodes (.class ) para la JVM java.exe : Intérprete de Java. Ejecuta la aplicación (.class ) compilada. jdb.exe : Depurador de Java. javadoc.exe : Generador de documentación. jar.exe : Compresor de ficheros. Programación Orientada a Objetos
Entornos de desarrollo – IDEs IDEs ( Integrated Development Environment ): Entornos de desarrollo integrados que permiten editar código Java, compilarlo y ejecutarlo sin tener que cambiar de aplicación ( debug gráfico). Ejemplos: Netbeans (http://www.netbeans.org/) Eclipse (http://www.eclipse.org/) BlueJ (http://www.bluej.org/) Programación Orientada a Objetos
Bytecode y máquina virtual de Java (JVM) Bycodes Es el c ódigo "compilado" que puede ser interpretado/ejecutado en cualquier máquina que tenga instalada la JVM correspondiente. Es independientemente del procesador utilizado. Es la salida del compilador de Java, que NO es ejecutable en la máquina física, sino que es un conjunto de instrucciones de alto nivel ejecutables/interpretables por una Máquina Virtual de Java (JVM) específica para la máquina física particular. Programación Orientada a Objetos
Bytecode y máquina virtual de Java (JVM) La JVM interpreta los 'bytecodes' (*.class) creados por el compilador ( javac.exe ) y los convierte a código particular de la CPU utilizada Independencia de la plataforma Las JVMs están implementadas para las distintas plataformas, pero interpretan el mismo bytecode programas portables Programación Orientada a Objetos
Desarrollo y ejecución de aplicaciones Para desarrollar y ejecutar aplicaciones en Java: Compilador : Analiza el código fuente (*. java ) y genera los ficheros con bytecode (*. class ). Se genera un archivo “. class ” por cada clase. Intérprete : Interpreta y ejecuta los programas previamente compilados (*. class ) Ambas herramientas de desarrollo están incluidas en la JDK. Programación Orientada a Objetos puede ver que hay tantos archivos .class como clases en el c ó digo fuente.
Desarrollo y ejecución de aplicaciones HolaMundo. java >>javac HolaMundo.java HolaMundo. class >>java HolaMundo JVM Errores de compilación Código fuente (.java) Compilador javac Bytecode (.class) Intérprete java EJECUCIÓN En la línea de comandos: En la línea de comandos: Programación Orientada a Objetos
Creación de un programa El proceso de creación de un programa desde su escritura hasta su ejecución comprende los siguientes pasos: Escritura del código fuente ( . java ) Compilación del código fuente (.class ) Interpretación de los bytecodes por la JVM
Creación de un programa 1.- Editamos un fichero de texto y lo salvamos con extensión .java Incluirá la definición de una o más clases. Generalmente cada clase va en un fichero llamado igual que la clase con extensión .java Dentro de un fichero sólo puede haber una clase pública, y si la hay, esta debe llamarse igual que el fichero. Puede haber otras clases no públicas, como una clase anidada dentro de otra, p.e.: “clase Nodo (no pública) dentro de la clase ListaEnlazada (pública) en un fichero llamado ListaEnlazada.java”.
Creación de un programa 2.- Desde la línea de comandos puede compilarse invocando al compilador javac : >>javac HolaMundo.java
Creación de un programa 3.- Se genera un fichero . class interpretable por la JVM. 4.- Lo interpretamos mediante el intérprete invocando a la máquina virtual de java ( java ) , que lo traduce y ejecuta paso a paso: >>java HolaMundo.class
Desarrollo y ejecución de aplicaciones F1: edición .java F2: compilación .class F3: carga El cargador de clases lee los .class que contienen Bytecodes del disco a memoria
El verificador de Bytecodes confirma que sean válidos y no violen las restricciones de seguridad de Java La JVM lee los códigos de bytes y los compila JIT (just In Time) Desarrollo y ejecución de aplicaciones F4: verificación F5: ejecución
Configuración de las variables PATH y CLASSPATH En una consola MS-DOS, sólo se pueden ejecutar los programas que se encuentran en los directorios indicados en la variable PATH del ordenador (o en el directorio actual o activo). CLASSPATH indica el lugar donde se encuentran tanto las clases de las librerías de Java (API) como otras clases de usuario. Programación Orientada a Objetos
Configuración PATH y CLASSPATH 1ª Solución: Fichero .bat con los valores de estas dos variables. Cada vez que se abre una consola se debe ejecutar el fichero: set JAVAPATH=C:\jdk1.1.7 set PATH=.;%JAVAPATH%\bin;%PATH% set CLASSPATH=.\;%JAVAPATH%\lib\libr.zip;%CLASSPATH% … Programación Orientada a Objetos
Configuración PATH y CLASSPATH … 2ª Solución : Añadir estos valores de forma permanente. Windows: Propiedades del entorno Opciones Avanzadas Variables de entorno 3ª Solución : Opción –classpath al compilar o ejecutar. P.e., MiPrograma.java necesita la librería OtrasClases.jar: javac -classpath .\;G:\d1\OtrasClases.jar MiPrograma.java java -classpath .\;G:\d1\OtrasClases.jar MiPrograma Programación Orientada a Objetos
Configuración PATH y CLASSPATH Programación Orientada a Objetos
Ediciones de Java Herramientas para desarrolladores Java https://www.oracle.com/es/downloads/ Ditribuciones Java Java SE (Java Standard Edition ) Java EE ( Java Enterprise Edition ): Incluye características adicionales como servlets , JSP, JDBC, JavaBeans, etc. Java ME ( Java Micro Edition ): Colección de APIs para dispositivos con recursos limitados ( PDAs , teléfonos móviles, electrodomésticos…) … Programación Orientada a Objetos
Ediciones de Java En la asignatura los programas se compilarán y ejecutarán dentro de Netbeans , en vez de desde la línea de comandos. Un Entorno de Desarrollo Integrado ( IDE ) contiene: Un editor para escribir códigos fuentes Un compilador para generar los byteCode para la JVM Un intérprete para ejecutar los programas creados Un depurador y opciones de depuración Ayuda y/o documentación de consulta
Elementos del lenguaje Java
Creación de un programa Un programa Java consta de una o más clases independientes. Las clases “de objetos” permiten describir las propiedades y habilidades de los objetos de la vida real que el programa tiene que representar. Un objeto es una realización concreta (instancia) de una descripción de clase. Dicha clase puede verse como el tipo de objeto.
Creación de un programa Si queremos hacer un programa imperativo, creamos una clase main : class Ejercicio{ // métodos estáticos // método main public static void main ( String arg []){ /*Escribimos aquí las instrucciones del método main */ } }
Creación de un programa - Ejemplo Si queremos hacer un programa imperativo, creamos una clase main : class HolaMundo{ public static void main(String arg[]){ /* Escribimos en pantalla */ System.out.println("Hola Mundo"); } }
Creación de un programa - Ejemplo Del ejemplo anterior se observa que: Es una clase llamada HolaMundo (igual que el fichero, este además lleva extensión .java ) Tiene un método llamado main Es un método void : No devuelve nada Tiene el modificador static : es un método de clase, no de objeto. Lo llama la JVM automáticamente cuando le damos el nombre de la clase al intérprete. El programa empieza a ejecutarse desde ahí. Es public porque la JVM lo va a ejecutar. Toma un argumento arg de la clase String , los corchetes [] indican que es un array de String , que guarda los posibles argumentos.
Creación de un programa - Ejemplo Del ejemplo anterior se observa que: Se invoca al método println() del objeto out de la clase System de la biblioteca de Java. El argumento de println es una cadena de caracteres. Instrucciones separadas por ; Espacios en blanco y comentarios no afectan a la salida.
Comentarios Los comentarios sirven para el lector humano, no son procesados por el compilador, pero es una buena práctica comentar los programas. Modalidades: Bloque de comentarios: /* . . . */ /* -------------------------------------------------------------------- * Este es un bloque de comentarios. Los dos primeros caracteres “/*” * abren el bloque de comentarios. Los dos siguientes símbolos cierran el * bloque: */ Comentario en una línea: // // Tras estas 2 barras, todo lo que hay en la línea es comentario. Documentación con: /**...*/ el programa javadoc del SDK puede generar de manera automática documentación del código en comentarios, y los introduce con este formato de comentario.
Comentarios Ejemplos de documentación creada por javadoc /** Ejemplo de documentación automática con javadoc @author José Vélez @versión 1.0 */ /** * Descripción de la función principal * @param nombre_parámetro descripción * @return descripción * @throws nombre_clase (de excepción) descripción */
Identificadores Son identificadores: 39 Identificadores Ejemplo Por convenio… Clases Interfaces Métodos constructores Jugador Pila Jugador Inicial en mayúscula y resto en minúsculas. Métodos acelerar frenar En minúsculas y si hay varias palabras, las iniciales excepto la primera, en mayúsculas. Variables barcosHundidos , numJugadores Argumentos formales y variables locales punto, velocidad Constantes declaradas con el atributo final NUM_COCHES Identificador completo en mayúsculas y separación de palabras con guión bajo Sintaxis: está permitido como identificador cualquier cadena de caracteres de Unicode (excepto palabras reservadas), que empiece con una letra seguida de una secuencia de caracteres en la que puede haber letras (a..z, A..Z), números (0,1,..,9) o el carácter subrayado “_” o “$”.
Identificadores Java distingue mayúsculas de minúsculas Cuando un nombre consta de varias palabras es habitual poner una a continuación de otra: Ejemplos : elMayor() VentanaCerrable RectanguloGrafico addWindowListener() Clases e interfaces comienzan siempre por mayúscula Ejemplos: Geometria , Rectangulo
Identificadores Objetos , métodos y variables miembro , variables locales de los métodos, comienzan siempre por minúscula: Ejemplos: main(), dibujar(), etc. Los nombres de las variables finales , es decir, de las constantes, se definen siempre con mayúsculas : Ejemplos: PI, MAXIMO
Palabras reservadas abstract boolean break byte case catch char class continue default do double extend false final finally float for if implements instanceof int interface long native new null package private public return short static super switch synchronized this threadsafe transient true try void volatile while
Tipos primitivos abstract boolean break byte case catch char class continue default do double extend false final finally float for if implements instanceof int interface long native new null package private public return short static super switch synchronized this threadsafe transient true try void volatile while
Control de flujo abstract boolean break byte case catch char class continue default do double extend false final finally float for if implements instanceof int interface long native new null package private public return short static super switch synchronized this threadsafe transient true try void volatile while
Capacidades POO abstract boolean break byte case catch char class continue default do double extend false final finally float for if implements instanceof int interface long native new null package private public return short static super switch synchronized this threadsafe transient true try void volatile while
Tipos primitivos, variables y constantes Los tipos primitivos están predefinidos en el lenguaje: Es posible declarar variables de estos tipos y asignarles valores mediante el operador asignación = Tipos primitivos Valores de las variables boolean true, false char Caracteres unicode 16 bits byte Entero (corto) con signo 8 bits short Enteros con signo 16 bits int Enteros con signo 32 bits long Entero (largo) con signo 64 bits float Reales 32 bits double Reales 64 bits
Expresiones Las expresiones pueden contener constantes literales (valores constantes de tipos primitivos), variables, operadores, llamadas a métodos… NOTA: null es el único literal objeto. Puede asignarse a variables que sean referencias a objetos de cualquier clase. 47 Tipo primitivo Ejemplos de valores constantes que pueden tomar las variables de tipos primitivos boolean true, false int 176, -52, 4 long 176L, 52l float 32.45F, 54.46f double 3.1415, 135.23, 3.14E2, 19e10 byte 120, -3 char ‘a’, ’A’, ‘?’, ‘7’, ‘0’, ‘\n’, ‘\t’, ‘\\’, ‘\’’, ‘\”’
Valores especiales de tipo carácter Caracteres especiales
Variables y expresiones con tipos primitivos <tipo> <identificador> [,<identificador>]; <identificador> = <expresión de inicialización> ; [final] <tipo> <identificador> = <expresión de inicialización > ; int mainCont , auxCont ; //Declaración de dos enteros mainCont = 2 ; //Inicialización de un entero int i = 5 ; //Declaración e inicialización de un entero final double PI = 3.1416 ; //Declaración e inicialización de una cte real En Java todos los datos de un programa o bien son objetos o son variables de alguno de los tipos primitivos (añadidos al lenguaje por razones de eficiencia) . La definición de una variable de un tipo primitivo sigue la siguiente sintaxis : Ejemplos:
Tipo carácter Tipo Tamaño en bytes Descripción Valor por defecto Sintaxis Ejemplo de uso char 2 Caracteres UNICODE ‘\u000000’ '[\u[0-9] + |.]' char c = 'ñ'; char D = '\u13'; Expresiones básicas Un valor de tipo char en Java es un carácter del estándar UNICODE codificado en 16 bits. Unicode codifica caracteres y símbolos de múltiples idiomas. Las constantes de tipo carácter en Java aparecen entre comillas simples. Ejemplos: 'A’ 'a’ ';’ '\u0108' (carácter UNICODE 0108 en base hexadecimal, que corresponde al 264 en base decimal)
Expresiones básicas Tipo Carácter: char : 16 bits ‘\u0000’ hasta ‘\ uFFFF ’ Unicode Se escriben entre comillas simples. También está permitido la secuencia de escape \ Ejemplo: ‘\t’ representa un tabulador También se puede poner directamente el código Unicode Ejemplo: ‘\u0041’ representa el carácter A
Variables Declaración e inicialización de variables Ejemplos int x; // Declaración de la variable primitiva x. Se inicializa a 0 int y = 5; // Declaración de la variable primitiva y. Se inicializa a 5
Constantes con identificador (no literales) Si el valor de una variable no puede modificarse durante la ejecución del programa, esta se declara con el modificador final , y se inicializa en la declaración. Ej.: //declaración de constantes: final byte NUM_JUGADORES = 11; //declaración de variables: int a, b; int c = 3; // declaración e inicialización a = 8; // el valor de a es 8. b = 5*c - a - NUM_JUGADORES; // el valor de b es -4; Tipos básicos o primitivos, variables y constantes
Programación Orientada a Objetos Elementos del Lenguaje JAVA DECLARACIÓN DE CONSTANTES: final Tipo idConstante = Valor ; Ejemplos: final int MINIMO = 100; final double PRECISION = 0.001; final double ALTURA_MEDIA = 29.5;
Tipos numéricos Tipo Tamaño en bytes Descripción Valor por defecto Ejemplo de uso byte 1 Enteros desde -128 a 127 byte B = 100; short 2 Enteros desde -32,768 hasta 32,767 short s = -8000; int 4 Enteros desde -2 31 hasta 2 31 -1, (desde -2,147,483,648 hasta 2,147,483,647) int i = 1400000; long 8 Enteros desde -2 63 hasta 2 63 -1 (desde -9,223,372,036,854,775,808 hasta 9,223,372,036,854,775,807 ) L long l = -53lL; float 4 Reales desde -3.4 × 10 38 hasta +3.4 × 10 38 +0.0f float x = -1.21f; double 16 Reales largos desde -1.8×10 308 hasta -1.8×10 308 0.0 double pi = +3.14; float temperatura = 257.0 f ; byte temperaturaTruncada = ( byte ) temperatura; // casting char caracter = 'A' + 10; System.out.println (temperatura); System.out.println ( temperaturaTruncada ); System.out.println ( caracter ); // imprime una K Expresiones básicas
Expresiones Operadores básicos En Java hay 46 operadores. Operador asignación = variable = expresión; a = a + 4; Asigna el valor de expresión a la variable Operadores aritméticos Binarios + Suma - Resta * Multiplicación / División entera : Resultado entero para operandos enteros, División de reales : Resultado real para operandos reales. % Módulo , n%m es el resto de la división entera n/m Monario - Cambio de signo , -expresión invierte el signo de expresión.
Expresiones Operadores básicos Operadores de relación Son binarios. Los operandos son expresiones numéricas. El resultado de la operación es booleano. < menor que <= Menor o igual que == Igual a != Distinto >= Mayor o igual que > Mayor que Operadores booleanos (Operandos y resultado booleanos) ! No (monario) && y (binario) || o (binario)
Reglas de precedencia de los operadores 59 Mayor prioridad Menor prioridad En las 5 siguientes transparencias, aparecen en recuadros amarillos los más usados
Operador Detalle Binario Unitario Ejemplo + Suma o declaración de positivo X X a + b, +a - Resta o declaración de negativo X X a – b, -a * Producto X a * b / División X a / b % Resto de la división de dos números enteros X a % b += Incremento en varias unidades de una variable X a += b -= Decremento en varias unidades de una variable X a -= 5 *= Multiplicación de una variable sobre ella misma X a *=3 /= División de una variable sobre ella misma X a /= b %= Resto la división de una variable sobre ella misma X a %=4 Solo para enteros ++ Post o pre-incremento en una unidad de una variable X a++, ++a -- Post o pre-decremento en una unidad de una variable X a--, --a Aritmética con tipos numéricos int a = 12; a *= 2; int b = a++; // se asigna a a b y luego se incrementa a System.out.println (a); System.out.println (b); 25 24
Elementos del Lenguaje JAVA Operadores unarios Prefijo: resultado = ++x; // primero se incrementa x y después se asigna resultado = --x; // primero se decrementa x y después se asigna - Postfijo: resultado = x++; // primero se asigna x y después se x incrementa resultado = x--; // primero se asigna x y después x se decrementa Ejemplo: int resultado, x = 10; resultado = ++x; // x vale 11 y resultado vale 11 resultado = --x; // x vale 10 y resultado vale 10 resultado = x++; // x vale 11 y resultado vale 10 resultado = x--; // x vale 10 y resultado vale 11
Programación Orientada a Objetos Elementos del Lenguaje JAVA
Elementos del Lenguaje JAVA class IncDec{ public static void main(String arg[]){ int a = 1; int b = 2; int c = ++b; int d = a++; c++; System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); System.out.println("d = " + d); } } Salida a = 2 b = 3 c = 4 d = 1
Operadores Otros operadores aritméticos Nótese que primero se opera y después se asigna
Operaciones relacionales para tipos numéricos Operador Descripción Ejemplo == Igualdad a == b > Mayor a > b < Menor a < b >= Mayor o igual a >= b <= Menor o igual a <= b != Distinto a != b Expresiones básicas int a = 12; int b = ++a; // a se incrementa en una unidad y se asigna a b System.out.println (a == b); System.out.println (a >= b); System.out.println (a != b); System.out.println (a <= b); true true false true
Tipo booleano Operadores lógicos Tipo Tamaño en bytes Descripción Valor por defecto Sintaxis Ejemplo de uso boolean indefinido cierto o falso false true | false boolean c = true; Operador Descripción Unitario Binario Ejemplo & Conjunción (and) X a&b | Disyunción ( or ) X a|b && Conjunción impaciente o perezosa (and) X a&&b || Disyunción impaciente o perezosa ( or ) X a||b ^ Disyunción exclusiva (xor) X a^b ! Negación (not) X ¡a &= Asignación con conjunción X a&=b |= Asignación con disyunción X a|=b Expresiones básicas boolean A = true; boolean B = false; boolean C = B && (A || B); //Deja de evaluarse en el && boolean D = A || (3 == 2+1); System.out.println (C); System.out.println (D); false true
Operadores lógicos Expresiones básicas AND ( &&) y OR (||) : Tienen la misma tabla de verdad que & y | respectivamente, pero en caso de qu e sea suficiente evaluar el primer operando para conocer el resultado de la expresión ya no evalúan más términos de la expresión. AND (&) y OR (|) → S iempre evaluarán ambos operandos, sea cual sea el resultado de la primera evaluación. Además, estos sirven para operaciones de bit.
Operaciones de bit con tipos numéricos Operador Detalle Binario Unitario Ejemplo & Conjunción (and) X a&b | Disyunción (or) X a|b ^ Disyunción exclusiva (xor) X a^b << Desplazamiento binario a la izquierda rellenando con ceros X a<<3 >> Desplazamiento binario a la derecha rellenando con el bit más significativo X a>>3 >>> Desplazamiento binario a la derecha rellenando con ceros X a>>>3 ~ Negación binaria X ~a Expresiones básicas con operaciones de bit int A = 0x5E; byte B = -3; short C = 0b111; System.out.println (A); System.out.println (B); System.out.println (C<<1); System.out.println (A | (B & C)); 94 -3 14 95
Control del flujo del programa Instrucciones de control del flujo de los programas en Java.
Control del flujo Ámbitos y sentencias Un ámbito se inicia con el carácter { y se termina con el carácter } . Los ámbitos se utilizan para: Definir qué sentencias están afectadas por una declaración (función, clase…) o por una instrucción de control de flujo ( if , while ...). Agrupar lógicamente sentencias. Los ámbitos se pueden anidar y dentro de un ámbito siempre puede definirse otro. Las declaraciones de las variables son locales al ámbito en que se declaran.
Control de flujo Ámbitos y sentencias { int a; a = 25; int c = 15; //Aquí 'a' vale 25 y 'c' vale 15 { int b; b = 2; // int c = 12; Java no deja definir 2 variables con mismo nombre en un ámbito //Aquí 'a' vale 25, 'b' vale 2 } //Aquí 'a' vale 25, 'c' vale 15 y 'b' no está declarada } { int a;a = 25; int c = 15;{ int b;b = 2;}} En Java, el tabulado (o indentación ) a nivel de ámbito es una convención muy aconsejable, aunque no afecte a la compilación: Nótese que el siguiente código ilegible es equivalente al anterior:
Control de flujo Estructuras de control de selección: if-else La sentencia if va seguida de una expresión lógica (booleana) que debe ir siempre entre paréntesis . Si se cumple la expresión lógica, se ejecuta la sentencia o el ámbito siguiente al if . En otro caso se ejecuta, si existe, la rama else . donde: la parte que va dentro de [ ] es opcional y | significa ‘o’ <ámbito> es un bloque de sentencias entre llaves <sentencia> una única sentencia. if (< expression booleana>) <ámbito> | <sentencia> [ else <ámbito> | <sentencia>]
If simple if (< expresión_booleana >) sentencia_o_ámbito_si_true [ else s entencia_o_ámbito_si_false ] // opcional //expresión booleana entre paréntesis 73 // Ejemplo: if (b != 0){ // ámbito resultado = a/b; System.out.println (“El resultado es : ” + resultado); } // Ejemplo: if (b != 0) resultado = a/b; // sentencia Estructuras de control de selección: if-else NOTA: + es el operador concatenación de cadenas de caracteres
Estructuras de control de selección: if-else If simple if (< expresión_booleana > ) sentencia_o_ámbito_si_true [ else s entencia_o_ámbito_si_false ] // opcional //expresión booleana entre paréntesis 74 // Ejemplo: if (b != 0) { resultado = a / b; System.out.println ("El resultado es : " + resultado); } else { // aquí las llaves se podrían omitir System.out.println ("División por cero"); }
Estructuras de control de selección: if-else Ifs en cascada o encadenados if (< primera_expresión_booleana > ) primera_sentencia_o_ámbito_si_true else if (< segunda_expresión_booleana > ) segunda_sentencia_o _ ámbito _ si_true … else if (< enesima_expresión_booleana > ) enesima_sentencia_o _ ámbito _ si_true else s entencia_o _ ámbito _ si_false // si son ámbitos (bloques) van // entre llaves if (a > b) { a = c; } else if (a < b) { a = d; } else { a = ; } Ejemplo:
Control de flujo Estructuras de control de selección: clásico switch-case-break-default Se evalúa una expresión de algún tipo de entero (primitivo o de clase envoltorio) o char , cuyo valor sirve para seleccionar el bloque de instrucciones que se ejecutan. Se ejecutan las sentencias del ámbito cuyo < valor cte > coincida con el resultado de la expresión. Si las sentencias de un case no terminan en break , se ejecutan las comparaciones siguientes. switch ( expresión ) { case < valor_cte > : < ambito > | <sentencia> ; break; case < valor cte > : < ambito > | <sentencia> ; break ; . . . [default: < ambito > | <sentencia> ;] // opcional } // < valor_cte > no puede ser un rango, sólo un valor constante.
Estructuras de control de selección: switch-case-break-default // Ejemplo: int num = 6; switch ( num ) { case 5 : { System.out.println ( "cinco" ); break; } case 6 : { System.out.println ( "seis" ); break; } default : { System.out.println ( “más" ); break; } } Ejemplo
Estructuras de control de selección: switch-case-break-default Ejemplo: dado un mes calcular su número de días class SwitchDemo1 { public static void main ( String [] args ) { int month = 9; int year = 2021; int numDays = 0; switch ( month ) { case 1: numDays = 31; break; case 3: numDays = 31; break; case 5: numDays = 31; break; case 7: numDays = 31; break; case 8: numDays = 31; break; case 10: numDays = 31; break; case 12: numDays = 31; break; ….
Estructuras de control de selección: switch-case-break-default Ejemplo: dado un mes calcular su número de días case 4: numDays = 30; break; case 6: numDays = 30; break; case 9: numDays = 30; break; case 11: numDays = 30; break; case 2: if ((( year % 4 == 0) && !( year % 100 == 0)) || ( year % 400 == 0)) numDays = 29; else numDays = 28; break; default: System.out.println (" Invalid month ."); break; } System.out.println (" Number of Days = " + numDays ); } // end main } // end class
Estructuras de control de selección switch-case-break-default Ejemplo: dado un mes calcular su número de días (de forma más simplificada) class SwitchDemo2 { public static void main ( String [] args ) { int month = 9; int year = 2021; int numDays = 0; switch ( month ) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: numDays = 31; break; case 4: case 6: case 9: case 11: numDays = 30; break; // . . . continúa:
Estructuras de control de selección switch-case-break-default Ejemplo: dado un mes calcular su número de días (de forma más simplificada) // . . . continúa case 2: if ((( year % 4 == 0) && !( year % 100 == 0)) || ( year % 400 == 0)) numDays = 29; else numDays = 28; break; default: System.out.println (" Invalid month ."); [break;] } System.out.println (" Number of Days = “ + numDays ); } }
Programación Orientada a Objetos Estructuras de control de selección: operador condicional Operador condicional (ternario) : ExpresionBooleana ? valor1:valor2 Si la expresiónBoolena es cierta devuelve valor1 y si es falsa devuelve valor2 . Ejemplo: (h>=0 && h<24)? h:0; NOTA: Este operador probablemente no se va a usar. Es más habitual usar un if-else equivalente.
Programación Orientada a Objetos Estructuras de control - Ejemplo Operador condicional ternario: (h>=0 && h<24)? h:0; // Equivale a: if ((h>=0) && (h<24)) return h; else return 0;
Control de flujo Estructuras de control de repetición for La estructura de control for permite repetir una sentencia o un ámbito un número concreto de veces. El número de repeticiones debe ser conocido, o bien, se debe conocer una expresión que lo calcule. for (<expresión inicialización>;<expresión booleana>;<expresión incremento>) <ámbito> | <sentencia>;
Estructuras de control de repetición for for Ejemplo for ( int cont = 0; cont < 100; cont ++){ a = a*b/ cont ; //La primera vez que se ejecuta esta línea cont vale 0 //La última vez que se ejecuta cont vale 99 } //Aquí la variable cont no existe (si existiese valdría 100) inicialización Expresión booleana. Si se cumple se ejecuta el bloque Expresión incremento. Cada vez que se ejecuta el bloque se incrementa el contador. 85
Programación Orientada a Objetos Estructuras de control de repetición for for Ejemplo: 1 2 3 4 5 6 7 8 9 10 for (int i = 1; i <= 10; i ++) { System.out.println (" i = " + i ); }
Programación Orientada a Objetos Estructuras de control de repetición for Ejemplo: total = 0; for (int i = 1; i <= 10; i ++){ for (int j = 1; j <= i ; j++ ) System.out.print (‘*’); System.out.println (); }
Programación Orientada a Objetos Estructuras de control de repetición for i = 2 total = 0 i = 4 total = 2 i = 6 total = 6 i = 8 total = 12 i = 10 total = 20 i = 12 total = 30 i = 14 total = 42 i = 16 total = 56 i = 18 total = 72 i = 20 total = 90 Ejemplo: total = 0; for (int i = 2; i <= 20; total += i , i +=2){ System.out.println (“I = ” + i + “ total = “ + total); }; Nota: en el curso sólo se va a incrementar en la
Programación Orientada a Objetos Estructuras de control de repetición for double funds = 1.00; int itemsBought = 0; for (double price = .10; funds >= price; price += .10) { funds -= price; itemsBought ++; } System.out.println ( itemsBought + " items bought."); System.out.println ("Change: $" + funds); Ejemplo:
Programación Orientada a Objetos Estructuras de control de repetición for int itemsBought = 0; int funds = 100; for (int price = 10; funds >= price; price += 10) { itemsBought ++; funds -= price; } System.out.println ( itemsBought + " items bought."); System.out.println ("Money left over: "+ funds + " cents"); ------------------------- 4 items bought. Money left over: 0 cents Ejemplo:
Control de flujo Estructuras de control de repetición: while while permite repetir un ámbito mientras se cumpla una condición. S e usa principalmente cuando el número de iteraciones no es concreto, sino que depende del resultado de evaluar una condición (expresión booleana). Ejemplo: while (< expresión booleana>) <ámbito> | <sentencia> while (a > b) { b = D * 25; a--; } Expresión booleana. Si se cumple (si es verdadera) se ejecuta el ámbito
Control de flujo Estructuras de control de repetición: do- while do while similar al anterior salvo que obliga a ejecutar una primera iteración antes de evaluar la condición. Ejemplo: do { b = D * 25; a--; } while (a > b); do <ámbito> | <sentencia> while (<expresión booleana>); Expresión booleana. Si se cumple se ejecuta el bloque otra vez
Control de flujo break y continue Dentro de un for o while se puede interrumpir la ejecución normal mediante: La instrucción break dentro de un bucle for o while detiene la iteración y saltando a ejecutar lo haya después del bucle (se sale del bucle). La instrucción continue dentro de un bucle for o while : detiene la iteración actual sin ejecutarse lo que hay después de continue y vuelve a la sentencia de evaluación (y decide si entra en la siguiente iteración o si hay que salir del bucle). break y continue pueden utilizarse con etiquetas para salir de varios bucles simultáneamente hasta alcanzar el bucle etiquetado. Esto no se va a usar. Generalmente sólo usaremos break en la instrucción switch-case. La sentencia return fuerza la terminación de un método y devuelve un valor. while (<condición>) { <sentencia> <sentencia> if (< condicion >) break ; } else if (<condición>) continue ; <sentencia> <sentencia> <sentencia> } <sentencia> <sentencia>
Elementos del Lenguaje JAVA Conversión de tipos AUTOMÁTICA: Se realiza al asignar un valor (o expresión) de un cierto tipo, a una variable de un tipo diferente. Para ello, la variable destino debe tener suficiente precisión, de lo contrario, habrá que hacer conversión explícita o casting. EXPLICITA (casting): Para convertir el valor de una expresión a un nuevo tipo se escribe delante de la expresión, entre paréntesis, el tipo al que se quiere convertir esta: ( nuevo_tipo ) expresión Ejemplo : int a = 100; byte b = (byte) a;//a es convertido a byte
Conversión de tipos Tabla de conversiones implícitas posibles (automáticas)
Conversión de tipos Conversión explícita (casting) Permite realizar un cambio de tipo a otro menor, lo que en general provoca pérdida de información. Otro ejemplo: float numReal = 17.5; int numEntero = ( int ) numReal ; // cambia el tipo del // valor de la expresión // a int .
Casting de expresiones Ejemplo : double d1 = 3.2; double d2 = 3.9999; double d3; int i1, i2; i1 = ( int )d1; // Convierte el valor de la expresión d1 a // int , i1 toma valor 3. i2 = ( int )d2; // i2 toma valor 3 d3 = i2; // convierte el valor de la expresión // i2 a double , d3 toma el valor 3.0 97
Inicialización por defecto de variables de tipos primitivos Inicialización por defecto de variables de tipos primitivos: Cuando declaramos una variable, Java la inicializa automáticamente : Las variables numéricas las inicializa a cero. Las variables referencia a objeto las inicializa a null . Las variables booleanas las inicializa a false. No obstante, puede hacerse también una inicialización explícita a estos o a otros valores.
Las clases envoltorio Los tipos de datos primitivos No son objetos Java No se pueden utilizar donde se requiere un objeto Existen clases Java estándar, en el paquete java.lang , llamadas clases envoltorio (o clases contenedoras o wrapper ) para tratar datos como los de los tipos primitivos, pero como objetos. Son: Double , Float , Integer , Long, Short, Boolean , etc.,
Para cada tipo primitivo hay una clase envoltorio definida: Clases envoltorio (o wrappers ) Tipo Primitivo Clase envoltorio int Integer boolean Boolean float Float double Double short Short char Character long Long etc … etc... 100
Clases envoltorio (o wrappers ) Tipo de una variable referencia a objeto El tipo de una variable referencia a objeto, también llamado el tipo del objeto, puede ser: - una clase, o - una interfaz. Si una variable se declara con una clase como tipo: Se le puede asignar la referencia a una instancia de esa clase o de cualquiera de sus subclases (clases derivadas). Esto se verá en próximos temas.
Construcción a partir de un valor primitivo pasado al constructor: Integer x = new Integer (3); //x es una referencia a objeto (de clase Integer ), que // guarda un 3 en su interior. Otra forma: no es necesario instanciarlos llamando al constructor, pues pueden manipularse como si fueran primitivos (esto es válido también para cualquier otra pareja primitivo- wrapper distinta de int-Integer ). Ej.: Integer x = 3; // Equivle a la instrucción anterior. Declara, instancia e inicializa // El compilador envuelve el 3 automáticamente antes de asignarlo // ( autoboxing ); Integer y = 5; Integer z = x + y; // Se suman Integer como si fueran int . System.out.println (z); // mostrará un 8 en pantalla. int w = z; // Al asignar un Integer a un int , lo desenvuelve // automáticamente ( unboxing ) antes de asignarlo a la // variable entera. w toma el valor 8. Integer v = x + 9; // desenvuelve x, se suma con el int 9 y envuelve el // resultado para asignarlo a v. Clases envoltorio (o wrappers ) 102
Todas las clases envoltorio excepto Character y Boolean heredan de la clase abstracta Number , por lo que tienen las mismas operaciones que sus correspondientes tipos primitivos: las operaciones aritméticas, comparaciones, etc … se pueden utilizar con objetos de clases envoltorio igual que si fueran de tipos primitivos. Ejemplo: Double x1 = 1.32; Double x2 = 4.21; if (x1 < x2) // operador de comparación : compara el contenido de los objetos . System.out.println (x1 + " < " + x2); Java envuelve y desenvuelve para colocar un tipo primitivo donde se espere un primitivo, y un wrapper donde se espere un wrapper . Ejemplo: Dada la función donde se espera un Integer : void nombre_función ( Integer x){ … } Puede ser llamada enviando un parámetro int : nombre_funcion (5); //java lo envuelve antes de pasarlo. Clases envoltorio (o wrappers ) 103
Para comparar datos primitivos en Java usamos operadores relacionales: <, >, <=, >=, ==, != Estos mismos sirven también para comparar objetos de clases envoltorio. Sin embargo, estos operadores de comparación no sirven para comparar objetos de otras clases (por ejemplo, las creadas por nosotros), pues con ellos se compararían referencias no los datos contenidos en los objetos). Ejemplo: Si deseamos saber si dos objetos ( p.e . de clase Coche ) son iguales, p.e . para realizar una búsqueda de un objeto coche en un array de objetos coche, no podemos usar el operador ==, pues este compararía las referencias de los dos objetos, es decir, la dirección de memoria a la que referencian, devolviendo true si es la misma, es decir, si son el mismo objeto. Pero esto no es lo que buscamos cuando deseamos comparar el contenido (los datos) de los objetos. Comparaciones de objetos de clases envoltorio 104
p1 p2 1) Sea el estado inicial de dos referencias a objetos de clase Punto , p1 y p2, en las direcciones de memoria 50 y 60: 2) Si realizamos la asignación p1 = p2; p1 p2 2 | 3 2 | 3 2 | 5 2 | 5 50 60 Al asignar un valor de una referencia a otra, ambas apuntan a la misma información, pero esta no se duplica. Se cumple: En este estado se cumple: Comparación de otros objetos Expresión Devuelve p1 == p2 (¿50 == 60?) false (p1.leerX() == p2.leerX()) && (p1.leerY() == p2.leerY()) false 50 60 Expresión Devuelve p1 == p2 true (p1.leerX() == p2.leerX()) && (p1.leerY() == p2.leerY()) true 105 Se está accediendo al mismo objeto.
p1.fijarX(p2.leerX()); p1.fijarY(p2.leerY()); 2) Si realizamos la asignación de los valores del objeto apuntado: p1 p2 1) Sea el estado inicial de dos objetos p1 y p2 de clase Punto , en las direcciones de memoria 50 y 60: 2 | 3 2 | 5 En este estado se cumple: Expresión Devuelve p1 == p2 (¿50 == 60?) false (p1.leerX() == p2.leerX()) && (p1.leerY() == p2.leerY()) false 50 60 p1 p2 2 | 5 2 | 5 En este estado se cumple: 50 60 Expresión Devuelve p1 == p2 (¿50 == 60?) false (p1.leerX() == p2.leerX()) && (p1.leerY() == p2.leerY()) true Comparación de otros objetos 106
Un array o tabla es una estructura de datos , cuyos elementos se almacenan en secuencia en posiciones de memoria contiguas. Todos los elementos de un array son del mismo tipo. En Java los arrays son objetos. Arrays
Arrays unidimensionales El acceso a los elementos de un array es directo: es posible almacenar y recuperar cada elemento directamente, especificando su posición (índice) en el array . El índice es una expresión entera, siendo el índice del primer elemento, 1 el del segundo, etc … 108 a -89 23 -42 11 43 índice 1 2 3 4 Acceso: a[0] a[1] a[2] a[3] a[4] Array a de 5 elementos enteros.
Arrays unidimensionales 109 Declaración: puede hacerse de dos formas: tipoElemento nombreArray [ ]; // tipoElemento es el tipo de // los elementos del array. // O bien: tipoElemento [ ] nombreArray ; Ejemplos: int v[ ]; // v es una referencia a un array de int float [ ] w;// w es una referencia a un array de w. Es más común usar esta // declaración Un array ( p.e . v , w ) es una referencia a objeto. Con esta declaración el array no está creado (instanciado). Se ha reservado espacio para las referencias a los objetos arrays v y w , pero no se ha reservado espacio en la memoria para guardar sus elementos. Para ello faltaría instanciar o construir los arrays .
Arrays unidimensionales 110 Construcción Para crear el array, es decir, para construirlo o instanciarlo, se usa el operador new junto al tipo de los elementos del array y su número (longitud del array) entre corchetes. Ejemplo: float [] velocidades; // sólo declaración velocidades = new float [26]; // construcción y asignación Ambas sentencias equivalen a: float [] velocidades = new float [26]; // declaración y construcción en la // misma línea. TipoElemento nombreArray [] = new tipoElemento [LONGITUD_ARRAY]; LONGITUD_ARRAY es un entero o expresión entera cuyo valor es el número de elementos de tipo TipoElemento que caben en él, o número de celdas reservadas para los elementos.
Arrays unidimensionales Ejemplos int diasMes []; //Igual que int [] diasMes ; diasMes = new int [12]; Las dos instrucciones anteriores equivalen a: int diasMes [] = new int [12]; Asignación de un valor a un elemento: diasMes [0] = 31; diasMes [1] = 28;
Arrays unidimensionales Declaración, construcción e inicialización a valores en la misma línea: En lugar de construir un array utilizando new, también es posible construirlo mediante una inicialización a una lista de valores, sin necesidad de utilizar new ni LONGITUD_ARRAY. Ejemplo: // Declaración, construcción e inicialización en la misma línea: int visitaSemanal [] = {31, 28, 31, 3, 25, 131, 150}; Esta inicialización reserva espacio para 7 elementos y a la vez les da esos valores. Es equivalente a: int visitaSemanal [] = new int [7]; visitaSemanal [0] = 31; visitaSemanal [1] = 28; // Otro ejemplo: String a[] = {" Avila "," Burgos","León","Palencia","Segovia "};
Arrays unidimensionales Cálculo de la longitud de un array: el atributo length Si se intenta acceder fuera de los límites de un array se produce error de ejecución. Los arrays son objetos y tienen una propiedad denominada length que contiene el número de elementos de reservados para el array (los que caben en él). Esta propiedad sólo se puede consultar (no es posible modificarla). Ejemplos: int visitaSemanal [] = {31, 28, 31, 3, 25, 131, 150}; System.out.println ( visitaSemanal.length ); // Escribe un 7 double [] v = new double [15]; System.out.print ( v.length ); // escribe 15
Programación Orientada a Objetos Arrays unidimensionales Declaración e inicialización de arrays . Ejemplos: int vector[]; // Declaración de un array. Se inicializa a null . vector = new int [10]; // Vector de 10 enteros, inicializados a 0. double v [] = {1.0, 2.65, 3.1}; // Declaración e inicialización de un // vector de 3 elementos con los Ejemplo: Uso del atributo length para calcular la suma de los elementos de un array de elementos de tipo double : double suma ( double [] w){ double s = 0.0; for ( int i=0; i < w.length ; i++) //recorrido por los elem . s = s + w[i]; // en cada iteración se accede a w[i] return s; }
Redimensionamiento de arrays El array se dice que es una memoria estática pues su tamaño se fija cuando se instancia el array y este no puede cambiar dinámicamente en tiempo de ejecución. Una forma de “aumentar” el tamaño de un array u cuando no quepan más elementos en él y se necesite guardar más elementos, es: crear un segundo array v de mayor tamaño, asignar todos los datos del primer array u a las primeras posiciones de v , y hacer que la referencia u pase a referenciar al nuevo array v así: u = v; El recolector de basura liberará la memoria ocupada por u anteriormente, pues dejará de estar referenciada . 115
Redimensionamiento de arrays Si se hace una asignación entre 2 variables array , estas referenciarán al mismo array . int u[] = {1,2,3,4,5}; // instancia e inicializa a 5 valores constantes. int v[] = new int [ u.length * 2]; // array v cuyo tamaño es el // doble que el de u. for ( int j = 0; j < u.length ; j++ ) v[j] = u[j]; // copia los elem de u en v. u = v; // Asignación de arrays . Los 5 elementos que // al principio se referenciaban desde u se // pierden, ya no se puede acceder a ellos y su // memoria se liberará. // Como resultado el array u se ha “redimensionado” al // tamaño del array v, pues referencia a él. El array u ahora // contiene los mismos elementos y un tamaño doble (ver dibujo). // NOTA: otra opción es incrementar el tamaño del array siempre en una misma //cantidad de celdas, cada vez que se redimensiona, en vez de duplicar tamaño. 1 2 3 4 5 1 2 3 4 5 u v
Arrays bidimensionales También llamados matrices. Sea una matriz de N filas y M columnas, se accede a sus elementos a través de 2 índices: índice de fila , i donde i < N índice de columna, j donde j < M . Declaración: tipo nombreMatriz [][]; Ejemplo : int b[][]; // declaración b = new int [7][5]; // instanciación o reserva de memoria para // 7x5 datos int . //Estas 2 instrucciones pueden escribirse en una sola así: int b[][] = new int [7][5]; b[3][4] = -10; // asignación de un valor a una posición. 117
Arrays bidimensionales Recorrido por filas de una matriz. Sea el tamaño de la matriz NUM_FILAS X NUM_COLUMNAS : // Se fija el número de fila y se recorren // todas las columnas (variando el índice de columna). // Se repite esta operación para cada fila. for ( int i=0; i < NUM_FILAS; i++) for ( int j=0; j < NUM_COLUMNAS; j++ ) { // Se procesa el elemento b[i][j], p.e. : variable = ... b[i][j] . . . } 118
Arrays bidimensionales Ejemplo: creación de una matriz 4x4 double matriz[][] = new double [4][4]; Arrays multidimensionales: Si se desea que las filas tengan distinto número de columnas, se declararía como un array de arrays . Para recorrer las filas utilizo el atributo lenght de las filas (que indica hasta dónde hay que iterar). Ejemplo: Matriz 3 arrays (de distintas longitudes) double matriz2[][] = new double [4][]; matriz2[0] = new double [4]; matriz2[1] = new double [2]; matriz2[2] = new double [3]; double x[] = {1, 2, 3, 4}; matriz2[3] = x;
Clases útiles – Arrays - Ejemplos int[] miarray1 = new int[10]; int[] miarray2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int [] miarray1 = new int [10]; for ( int i = 0; i < 10; i++) miarray1[i] = i; System.out.println ("Elementos: " + miarray1.length); String [] dias = {" lunes ", "martes", " miercoles ", " jueves ", " viernes ", " sabado ", "domingo"}; for ( int i = 0; i < dias.length ; i++) System.out.println (" Posicion : " + i + " contenido : " + dias[i]);
Clases útiles – Arrays - Ejemplos public class MiClase { private int identificador; private static int contador = 1; public MiClase (){ identificador = contador; contador++; } public int getId (){ return identificador;} } MiClase [] arrayObjetos = new MiClase [5]; for( int i = 0 ; i < 5; i++) { arrayObjetos [i] = new MiClase (); System.out.println (i + " ID: " + arrayObjetos [i]. getId ()); }
Clases útiles – Arrays - Ejemplos public class Matriz { int [][] datos; int dim ; public Matriz( int num ) { dim = num ; Random rnd = new Random (); datos = new int [ num ][ num ]; for ( int i = 0; i < num ; i++){ for ( int j = 0; j < num ; j++ ){ datos[i][j] = rnd.nextInt (); } } } }
123 / Las clases Cómo crear clases y objetos de esas clases en Java.
124 / Las clases Las clases Primero se define una clase y luego se pueden crear un número ilimitado de objetos de esa clase. Al definir una clase se define la interfaz (de los objetos que posteriormente se podrán crear) y la implementación. Definición de una clase: Identificación Miembros Clases internas Bloques de inicialización Por ejemplo: [Modificadores de clase] class < identificador > [parámetros][herencia][excepciones]{ [ propiedad|metodo | inicializacion | clase ]* } class Coche { //Aquí iría la implementación de la clase Coche }
Las clases Identificación Primera línea de la clase: nombre de la clase, clases de las que hereda, interfaces que implementa, excepciones parámetros de tipo.
Las clases Miembros: Datos miembros o propiedades Métodos miembros Estos pueden corresponder a instancias de clase (objetos particulares) o a la propia clase (sirven para todos los objetos de clase).
Las clases Clases internas Una clase interna es una clase definida dentro del ámbito de otra clase. Se utiliza sólo cuando está fuertemente unida a la clase huésped y sólo se va a usar desde esta. Cuando en un fichero se definen varias clases, sólo una de ellas puede estar declarada como pública, y el fichero debe llamarse como la clase pública: NombreClase.java L o habitual es escribir una sola clase por fichero. public class Stack { private class Node { Node next; int value; . . . } private Node top = new Nodo(); ... }
Las clases Conjuntos de instrucciones que inicializan datos antes de las llamadas a los constructores. Pueden usarse cuando hay inicializaciones comunes a varios constructores. Van en un ámbito anónimo (sin cabecera). public class Coche{ private int velocidad; private boolean enMarcha ; private final int numRuedas ; private final int numPuertas ; // inicializa a valores por defecto public Coche(){ } public Coche( int v, boolean enMarcha , int numPuertas ){ velocidad = v; this.enMarcha = enMarcha ; this.numPuertas = numPuertas ; } { // Bloque de inicialización: enMarcha =false; numRuedas = 4; // inicializa prop final } } Bloques de inicialización
Referencias a objetos Son variables de tipo referencia a objeto Se denominan variables referencia o referencias . Referencian a objetos de una determinada clase (incluidos arrays ). nombreClase refObjeto ; // refObjeto es una // variable referencia Se les puede asignar el valor null (objeto nulo o referencia cuyo valor no es una dirección de ningún objeto) refObjeto = null ;
130 / Java permite definir variables que sean referencias a objetos . La expresión de inicialización puede ser de dos tipos: Creación de un objeto, con la palabra reservada new seguida del nombre de la clase. Referencia a otro objeto ya creado. Referencias a objetos < nombre_clase > <identificador> [,<identificador>]; <identificador> = <expresión de inicialización> ; [final] < nombre_clase > <identificador> = <expresión de inicialización > ; Coche a, b, c; //Se declaran tres variables que apuntarán a objetos. a = new Coche (); //Se crea un coche y la variable “a” lo apunta. b = new Coche (); //Se crea otro coche y la variable “b” lo apunta. c = a; //La variable “c” apunta al mismo coche que “a”. Tipo Tamaño en bytes Descripción Valor por defecto referencia a objeto 4 Referencia a un objeto null
Inicialización de referencias a objetos Declaración e inicialización de variables referencia. Ejemplos: NombreClase refObjeto1; // Declaración de una referencia a un // objeto de clase NombreClase . // Se inicializa a null refObjeto1 = new NombreClase (); // La referencia ahora “apunta” al // nuevo objeto creado. Se ha utilizado // el constructor por defecto NombreClase refObjeto2; // Declaración de una referencia a un objeto // de clase NombreClase . refObjeto2 = refObjeto1 ; // Se inicializa al mismo valor que refObjeto1 // Ambas apuntan al mismo objeto: no hay 2 // objetos
132 / Diferencia entre objeto y referencia a objeto public class JuegoCoches { public static void main ( String [] args ) { Coche coche1 = new Coche(); Coche coche2 = new Coche(); Coche coche3 = coche1; coche1.acelerar(10); coche2.acelerar(20); coche3.parar(); } } En el ámbito de un método se opera con los parámetros que se le pasan y con miembros (métodos y propiedades) de la propia clase. El método main de JuegoCoches crea 2 objetos de la clase Coche. c1 c3 c2 velocidad = 10km/h velocidad = 20 km/h class Coche { boolean enMarcha ; int velocidad; Rueda r1 = new Rueda(); Rueda r2 = new Rueda(); Rueda r3 = new Rueda(); Rueda r4 = new Rueda(); void parar() { velocidad = 0; enMarcha = false ; } void acelerar( int incremento) { velocidad += incremento; enMarcha = true ; } int dameVelocidad () { return velocidad; } }
Las referencias reciben el nombre de punteros en otros lenguajes como C o Pascal. También se llaman enlaces en el ámbito de las estructuras de datos dinámicas. //Declaración de una referencia con identificador p: Punto p; // Esta declaración reserva memoria para una variable p, que puede // contener una dirección de memoria de un objeto de la clase // Punto, es decir, referencia a un objeto de clase Punto que // este todavía no existe: // p = new Punto(10, 13); // Instanciación de un objeto de clase Punto cuya // referencia es p. Reserva espacio para un objeto // de la clase Punto y lo inicializa a los valores // 10, 13 enviados al constructor: // NOTA: Las direcciones de memoria se representan gráficamente con una flecha en vez de con un número, pues el número no es relevante, ya que al programador sólo le interesa a qué objeto referencia p , no en qué posición de la memoria está el objeto referenciado. p Inicialización de referencias a objetos 133 p 10 13
Identificador de constante referencia nula: null null : es un valor constante de tipo referencia a objeto. null sirve para asignarlo a una variable referencia cuando se desea indicar que esta no contiene ninguna dirección de memoria asignada o válida, es decir, para indicar que la variable “no apunta a ningún objeto”. Ejemplo: Punto p; //p no está inicializada … p = null ; //asignación de la cte literal null a la variable p. //p contiene null , gráficamente se representa así: p Inicialización de referencias 134 p
El operador new Un objeto en java se crea (se instancia) con el operador new , que reserva espacio en la memoria para el objeto. Para crear un objeto, new debe ir seguido de una llamada a algún constructor de la clase del objeto a crear. El operador new crea un objeto nuevo de una clase especificada y devuelve una referencia a ese objeto (que es la dirección reservada para ese objeto en la memoria). Sintaxis general: // Declaración de la variable referencia NombreClase varReferencia ;. //Instanciación del objeto y asignación de su ref a la variable: varReferencia = new NombreClase ( args del constructor); Ejemplo: Punto p1, p2; p1 = new Punto(); p2 = new Punto(3,4); 135 3 4 p1 p2 MP
El operador new . Ejemplo . public class Ejemplo{ . . . public void nombreMetodo ( ){ Punto p1; Punto p2 = new Punto(); p1 = new Punto(1,2); p2 = p1; ... } } Declara la variable p2 y le asigna la referencia (o dirección) del nuevo objeto creado con new . Declara la variable p1 , a la que se podrá asignar cualquier referencia a un objeto de clase Punto . Asigna a la variable p1 la referencia al nuevo objeto creado con new inicializado a los valores 1, 2. Asigna a la variable p2 la referencia del objeto p1. Ahora p2 referencia al mismo objeto que p1. El viejo objeto al que apuntaba p2 ahora no tiene ninguna variable que lo apunte => por eso desaparecerá y la memoria que ocupa quedará libre (de ello se encargará el recolector de basura). p1 1 2 x y p2 0 0 x y p1 1 2 x y p1 p2 0 0 x y 136
El operador new La llamada al operador new hace lo siguiente: 1º) Reserva memoria dinámica (en tiempo de ejecución) para guardar un nuevo objeto, y todas sus variables instancia se inicializan a los valores estándar por defecto: null para variables referencia a objeto, false para booleanos y para tipos base. Punto p2 = new Punto(5,6); 2º) Después llama al constructor (mediante la llamada que sigue a new ) para inicializar el nuevo objeto con los parámetros deseados. Punto p2 = new Punto(5,6) ; 3º) Tras ejecutarse el constructor, el operador new devuelve la referencia es decir, la dirección de memoria del nuevo objeto creado. Si la expresión de llamada a new está a la derecha del = en una instrucción de asignación, esta dirección es almacenada en la variable referencia a objeto para que apunte o referencie al nuevo objeto creado. Así, una variable referencia es vista como un puntero a un objeto, es decir, apunta al objeto, y permite acceder a él y a sus datos. 5 6 x y Variable referencia a objeto Objeto apuntado 137 p2 Punto p2 = new Punto(5,6);
El operador new En resumen: El operador new permite reservar (y liberar) memoria dinámicamente , es decir, en tiempo de ejecución, para guardar objetos según las necesidades del programa. Al trabajar con memoria dinámica , recuerde que declarar una variable de tipo referencia a objeto no es suficiente para reservar memoria para el objeto, sino que se debe llamar al procedimiento new seguido de una llamada al constructor adecuado que lo inicialice. 138
// Ejemplo: clase Personaje package saludos; public class Personaje { // Datos: private String nombre; private String ocupacion ; private String colorPelo ; private String vestimenta; private String accesorio; private int edad; // Métodos: // Método constructor: Personaje( String name , String activ , String c, String v, String objeto, int age ){ nombre = name ; ocupacion = activ ; colorPelo = c; vestimenta = v; accesorio = objeto; edad = age ; } // Método constructor sin parámetros (inicializa a valores predeterminados) Personaje(){ nombre = ""; ocupacion = ""; colorPelo = ""; vestimenta = ""; accesorio = ""; edad = 0; }
// CONTINÚA EJEMPLO clase Personaje // Getters public String getActividad (){ return ocupacion ; } public String getVestimenta (){ return vestimenta; } public String getColorPelo (){ return colorPelo ; } public int getEdad (){ return edad; } // Setters : public void setEdad ( int age ){ edad = age ; } public void setColorPelo ( String color){ colorPelo = color; } public void setVestimenta ( String v){ vestimenta = v; } public void setOcupacion ( String actividad){ ocupacion = actividad; } public void setAccesorio ( String objeto){ accesorio = objeto; }
// CONTINÚA EJEMPLO clase Personaje // Otros métodos: public void saludar(){ System.out.println ("Hola, soy " + nombre + ", " + ocupacion + " de profesión " + " y tengo " + edad +" años."); System.out.println ("Me voy con mi " + vestimenta + " y con mi " + accesorio); System.out.println (); } public void disfrazarseBruja (){ vestimenta = "bata negra"; colorPelo = "gris"; accesorio = "escoba"; System.out.println ("Soy " + nombre + " y me he disfrazado de bruja."); System.out.println ("Me voy con mi " + vestimenta + " y con mi " + accesorio); System.out.println (""); } public void disfrazarsePiloto (){ vestimenta = "mono de ferrari "; colorPelo = "pelirrojo"; accesorio = "coche de carreras"; System.out.println ("Soy " + nombre + " y me he disfrazado de piloto."); System.out.println ("Me voy con mi " + vestimenta + "y con mi " + accesorio); System.out.println (); } // public void pintarEnPantalla (){ // . . . //} } // end class Personaje
// clase main que usa la clase Personaje package saludos; public class Saludos { public static void main ( String [] args ) { Personaje corredorCharles = new Personaje("Charles", "piloto", "moreno", "coche de rally", "mono", 30); Personaje brujaAmelia = new Personaje("Amelia", "bruja", "gris", "escoba", "bata negra", 70); corredorCharles.saludar (); brujaAmelia.saludar (); corredorCharles.disfrazarseBruja (); brujaAmelia.disfrazarsePiloto (); } } SALIDA POR PANTALLA EN LA EJECUCIÓN PROGRAMA: Hola, soy Charles, piloto de profesión y tengo 30 años. Me voy con mi coche de rally y con mi mono Hola, soy Amelia, bruja de profesión y tengo 70 años. Me voy con mi escoba y con mi bata negra Soy Charles y me he disfrazado de bruja. Me voy con mi bata negra y con mi escoba Soy Amelia y me he disfrazado de piloto. Me voy con mi mono de ferrary con mi coche de carreras
El recolector de basura Es el recolector de objetos no referenciados, es decir, no apuntados por ninguna referencia. En Java es preciso que un objeto esté referenciado por una variable referencia para poder acceder a él. En el momento en que un objeto deja de estar referenciado, la rutina de recolección de memoria no usada (llamada recolector de basura), libera la memoria ocupada y no referenciada, para que esta pueda ser reservada más adelante (con new ) cuando se necesite. Punto p1 = new Punto(1,2); p1 = null ; p1 ya no apunta a nada. Dejó de apuntar al obj . Objeto no apuntado por ninguna referencia y por tanto no accesible. El recolector de basura lo liberará. Objeto apuntado 1 2 x y Variable referencia al objeto p1 p1 1 2 x y
El recolector de basura El propio sistema recolecta los objetos en desuso (no referenciados), para aprovechar la memoria ocupada. Para ello, hay un proceso que se ejecuta periódicamente que libera la memoria de los objetos que no están referenciados por ninguna variable. Se trata del método System.gc () ( garbage collection ). En otros lenguajes no existe y hay que llamar explícitamente a las instrucciones adecuadas para liberar memoria que ya no se usará. En java, si no se quiere esperar a que lo haga el sistema automáticamente, se puede hacer una llamada a este método escribiendo “ System.gc (); ” en el programa. Ejemplo: void objetos() { Contador k, g, r, s; // creamos referencias a 4 objetos de clase Contador // Creamos 4 objetos de clase Contador: k = new Contador(); g = new Contador(); r = new Contador(); s = new Contador(); g = k; // g referencia al mismo objeto que k. El objeto original // de g será recolectado. k = null ; // el objeto al que apuntaba k sigue referenciado (por g). r = new Contador(); // el recolector libera el objeto original de r; } // se liberan los objetos actuales apuntados por g y r. 144
145 / Las clases Miembros de las clases Los miembros de una clase pueden ser de dos tipos: Propiedades: variables que se declaran en el interior de una clase también llamadas variables miembro. Métodos: funciones que tiene parámetros, que devuelven elementos y que pueden contener código. En Java, el identificador de una clase suele estar en mayúsculas y los miembros de una clase suelen estar en minúsculas. Coche velocidad:int enMarcha : boolean acelerar(int) parar() dameVelocidad():int Rueda radio:float presion:int r1,r2,r3,r4
146 / Las clases Definición de propiedades Las propiedades, o campos, sirven para dotar de estado al objeto o a la propia clase. Las propiedades son variables definidas dentro de una clase y pueden tomar valores independientes en cada objeto. propiedad ::= [mod control acceso] [mod uso] <tipo> <identificador> [= inicializa ]; O bien: [acceso] [ static ] [final] Tipo nombreAtrib [= Valor]; Si no se indica otra cosa se inicializan a su valor por defecto ( null los objetos, cero los tipos numéricos, false los booleanos...). class Coche { boolean enMarcha ; int velocidad ; Rueda r1 = new Rueda() ; Rueda r2 = new Rueda() ; Rueda r3 = new Rueda() ; Rueda r4 = new Rueda() ; } class Rueda { int presion = 2000 ; float radio = 6.28f ; }
Tipos de variables instancia o variables miembro Pueden ser: de tipo base o primitivo , guardan valores simples ( int , float … ). Ej.: int velocidad; boolean enMarcha ; de tipo “referencia a objeto” . El tipo del objeto es su clase. Una variable instancia declarada con un nombre de clase como tipo, sirve para almacenar en ella una referencia (o dirección de memoria) de un objeto de esa clase (la referencia es lo que se denomina en otros lenguajes un puntero, pues apunta dicho objeto en la memoria). NombreClase varReferencia ; Ejemplos: Punto p1, p2; // declaración de referencias a los objetos p1 y p2 de // clase Punto. Rectangulo rect ; // Podrá guardar como valor la dirección de memoria // de un objeto de clase Rectangulo . Cuando el tipo de // una variable es el nombre de una clase de objeto, // la variable es una referencia a objeto. 25 25 75 75 rect
Acceso a variables instancia desde un método de la clase Desde cualquier método de la clase se puede acceder a las variables instancia sólo con su nombre. variableMiembro = 8; Esto únicamente no es posible si en el ámbito desde donde se accede hay otra variable con su mismo nombre: las variables locales de un método de la clase ocultan al resto de variables con el mismo nombre que estén fuera de su ámbito {…}. Si se quiere acceder a una variable instancia (atributo) oculta se puede hacer referencia al objeto actual mediante this : this.variableMiembro =. . . ; //para acceder a una variableMiembro // del objeto que actual (el // que invocó al método // donde se encuentra).
Referencia al objeto que envía el mensaje: this La palabra reservada this es una referencia al objeto invocante. Dentro de un método de una clase de objeto s irve para nombrar al objeto que invocó al método . class Triangulo{ private double base; private double altura; ... public Triangulo( double base, double altura){ this.base = base; // Aquí this permite diferenciar a la variable instancia del // parámetro. this.altura = altura; } } this.base es el miembro base del objeto de clase Triangulo que llamó al método donde está this . Aquí evita el conflicto con el argumento que se llama igual. No sería necesario this si los parámetros tuviesen nombres diferentes a las variables instancia. Otro ejemplo de uso: cuando un método devuelve el mismo objeto que lo llamó puede hacerse mediante return this ;. 149
150 / Detalles de los métodos En esta sección se profundiza en el concepto de método.
151 / Las clases Definición de métodos miembro Los métodos son funciones definidas dentro de la clase. También se llaman mensajes. Se invocan sobre los objetos de esa clase o sobre la clase misma. método ::= [Mod acceso] [Mod uso] <tipo> <Id> ([ params ]) [ excepc ] [{[ implementación ]}] O bien: [acceso] [ static ] [final] tRetorno nombreMetodo ([ args ])[{[cuerpo del método]}] parámetros ::= <tipo> <identificador>[,<tipo> <identificador>]* excepciones ::= throws <tipo> [,<tipo>]* implementación ::= [sentencia]* class Coche { void parar () { // Código con la implementación } void acelerar ( int incremento ) { // Código con la implementación } float reparar ( float dinero , Taller t ) { // Código con la implementación } }
Definición de métodos miembro Su definición tiene dos partes: Cabecera: define lo que se debe conocer para su uso, es decir, el nombre del método, los parámetros y sus tipos y tipo del valor de retorno si lo hay ( void si no lo hay). Cuerpo o implementación: define lo que hace el método cuando el objeto recibe un mensaje para que este se ejecute. Sintaxis de la definición de un método: //cabecera: modAcceso modUso tipo nombreMetodo (tipo1 parametro1,…, tipoN parametroN ){ // cuerpo o implementación del método }
Definición de métodos miembro Cabecera Modificador de acceso al método : public , protected,private o si no hay modificador el método es friendly . Modificador de uso static : significa que el método no es de una instancia u objeto particular de la clase, sino que es un método de la propia clase que no corresponde a ningún objeto. No se invoca sobre un nombre de objeto, sino que la llamada se realiza así: nombreClase.nombreMétodo (. . .) P.e .: la clase Coche podría contener un método estático “ static int numCoches .. .“ que devuelva el número de objetos de clase Coche instanciados hasta el momento. 153
154 / Métodos y atributos de objeto o de clase Tipos de métodos: métodos de objeto (o de instancia): se pueden invocar sobre los objetos que se creen de esa clase. métodos de clase (también llamados estáticos ): se pueden invocar sobre la propia clase. En UML, los miembros estáticos se distinguen porque el nombre del método está subrayado. Tipos de atributos: Atributos de objeto (también llamados estáticos ): pertenecen a una instancia de objeto. Atributos de clase : no pertenecen a ninguna instancia de objeto.
155 / Detalles del modificador static En Java, para indicar que un método o una variable es de clase (o estático) se debe declarar usando la palabra reservada static . Dentro de un método estático no se pueden usar las propiedades de instancia (no estáticas) de la propia clase, porque no hay instancia, aunque sí se pueden usar propiedades estáticas. class Coche { private int velocidad; private static int cochesVendidos ; // Método de clase public static void venderCoche () { cochesVendidos ++; } //Métodos del objeto public void acelerar() { velocidad++; } public void parar() { velocidad = 0; } }
156 / Para acceder a un método de clase (estático) desde dentro de la clase solo hace falta utilizar el identificador del método seguido de los paréntesis y los parámetros en su caso. Para acceder a un método de clase (estático) desde fuera de la clase se utiliza el identificador de la clase seguido del identificador del método, los paréntesis y los parámetros. Acceso a los métodos de clase class Coche { private int velocidad; private static int cochesVendidos ; // Método de clase public static void venderCoche () { cochesVendidos ++; } //Métodos del objeto public void acelerar() { velocidad++; } public void pararYVenderCoche () { velocidad = 0; venderCoche (); } } // Llamada a un método static desde // otra clase: metodoExterno () { Coche. venderCoche (); }
Definición de métodos miembro Cabecera El identificador del método está precedido por el tipo del valor devuelto por el método (valor de retorno) o void si no devuelve nada. Si el método no devuelve ningún valor, es un procedimiento. Si devuelve un valor, el método es una función. Al nombreMetodo lo siguen los parámetros del método. Tras los parámetros puede haber un ámbito con la implementación. 157
158 / Detalles del modificador static Todo programa en Java comienza su ejecución en un método static denominado main . /** Programa en Java que muestra un mensaje de bienvenida */ class HolaMundo { // El método en el que comienza la ejecución del programa es main public static void main ( String [ ] arg ) { System.out.println ("Hola mundo"); } }
Definición de métodos miembro Elementos de la cabecera (continúa…): nombreMetodo es un identificador válido de Java. lista de parámetros precedidos por sus tipos : Los métodos aceptan parámetros (datos de entrada al método) como argumentos. Van entre paréntesis y separados por comas tras el nombre del método. Los parámetros son variables que sólo pueden usarse dentro del método. En la llamada se les asignan los valores necesarios para la ejecución del método. tipoi es cualquier tipo base o cualquier clase de objeto. parametroi es un identificador. La lista de parámetros puede estar vacía, en ese caso también es preciso escribir los paréntesis. 159
Definición de métodos miembro Cuerpo o implementación de un método. Es un ámbito de sentencias (entre llaves), con una secuencia de : Declaraciones de variables locales y Sentencias o instrucciones Declaraciones de variables locales. Se declaran generalmente al principio del bloque del método, aunque también pueden declararse en algún ámbito más interno donde se vayan a usar. Sólo existen mientras se ejecuta el bloque donde están declaradas. Son o bien de un tipo base, o referencias a objetos Sintaxis: tipo nombre1; // declaración tipo nombre2 = valor_inicial ; // declaración e inicialización Ejemplo: //declaración de variables locales double r; int i = 512; Punto p1 = new Punto(8, 2); Las sentencias simples y las declaraciones terminan con “;”. 160
161 / Las clases Valor de retorno de un método En el interior del método se usa return para indicar el valor devuelto o valor de retorno. Si un método indica que devuelve un valor, es imprescindible que todos los caminos del método terminen en return seguido de una expresión que resulte el valor de retorno. public class JuegoCoches { public static void main ( String [] args ) { Coche coche1 = new Coche(); Coche coche2 = new Coche(); Coche coche3 = c1; coche1.acelerar(10); coche2.acelerar(20); coche3.parar(); } } class Coche { boolean enMarcha ; int velocidad; Rueda r1 = new Rueda(); Rueda r2 = new Rueda(); Rueda r3 = new Rueda(); Rueda r4 = new Rueda(); void parar() { velocidad = 0; enMarcha = false ; } void acelerar( int incremento) { velocidad += incremento; enMarcha = true ; } int dameVelocidad () { return velocidad; } }
Valor de retorno de un método Valor de retorno de un método Los métodos devuelven un único valor o ninguno (especificando void como tipo del valor de retorno en la cabecera). Para devolver el valor de una expresión, dent ro del cuerpo de la función: return [ expresión] ; El tipo de la expresión coincide con el tipo del valor de retorno indicado en la cabecera. Si el método no devuelve nada se suele omitir la sentencia return o si se escribe, se omite la expresión así: return ; Cuando se ejecuta la sentencia return termina la ejecución del método, es decir, ya no se ejecutan más sentencias del método si las hubiera. 162
Métodos - Ejemplo class Punto { private int x; private int y; public double calcularDistanciaCentro () { double z; z= Math.sqrt ((x*x)+(y*y)); return z; } } Método Atributos
Referencia al objeto que invocó al método: this La palabra reservada this en una expresión dentro de un método miembro, es una referencia al objeto que invocó a ese método. class Triangulo{ private double base; private double altura; ... public Triangulo( double base, double altura){ this.base = base; // Aquí this permite diferenciar a la variable instancia del // parámetro. this.altura = altura; } } this.base es el miembro base del objeto de clase Triangulo que llamó al método donde está this . Aquí evita el conflicto con el argumento que se llama igual. No sería necesario this si los parámetros tuviesen nombres diferentes a las variables instancia. Otro ejemplo de uso: cuando un método devuelve el mismo objeto que lo llamó puede hacerse mediante return this ;. 164
//Creación de una instancia de Coche: Coche clioAlicia = new Coche(); .. clioAlicia.acelerar(20); // envío de mensaje a clioAlicia Definición de métodos miembro Llamada a un método miembro de una clase de objeto Un método que no sea static es invocado o llamado para su ejecución sobre una instancia específica de un objeto. El método se encuentra definido en la clase de dicho objeto y puede cambiar el estado del objeto que lo invocó. Para ejecutar un método miembro de un objeto: desde otra clase : se usa el operador punto ‘ . ’. nombre_objeto.nombre_metodo (param1,..., paramN ); desde un método de su misma clase : nombre del objeto y el operador punto se omiten. P.e .: en la transparencia siguiente, en el método irComoUnLoco () de la clase Coche , se envían los mensajes acelerar() y frenar() sin precederlos del nombre del objeto invocante ni del operador punto . Se aplican sobre el objeto que invocó al método irComoUnLoco () (objeto invocante). 165
p ackage carreras; public class Coche{ // propiedades: private int velocidad; private boolean enMarcha ; // método constructor: public Coche(){ velocidad = 0; enMarcha = false; } // otros métodos: public void acelerar ( int incremento){ if (incremento > 0){ velocidad = velocidad + incremento; enMarcha = true; } } public void frenar() { if ( enMarcha ) velocidad--; if (velocidad == 0) enMarcha = false; } public void irComoUnLoco ( int incremento){ for ( int i = 1; i<=10; i++){ acelerar(incremento); frenar(); } } } p ackage carreras; public class Circuito{ ... public static void main ( String [] args ){ int v = 60; Coche clioAlicia = new Coche(); Coche meganePepe = new Coche(); // Los siguientes métodos son invocados // por los objetos que preceden al operador . : clioAlicia.acelerar (v); meganePepe.acelerar (150); clioAlicia.frenar (); meganePepe.irComoUnLoco (200); } } 166 Sean las clases del mismo paquete: Coche en el fichero Coche.java, y Clase Circuito en el fichero Circuito.java
Definición de métodos miembro Envío o paso de parámetros a un método En java los parámetros son pasados siempre “por valor” a los métodos: Cuando se ejecuta el método, se reserva espacio en la memoria para los parámetros formales (los de la cabecera del método) y se les asigna una copia del valor de los correspondientes parámetros enviados en la llamada (parámetros actuales o reales). Significa que se pasa una copia del valor del parámetro actual que se envía en la llamada, y dentro del método se trabaja con la copia (parámetro formal). // en la siguiente llamada se copia o asigna el parámetro actual 20 // al parámetro formal del método acelerar. int vel = 20; acelerar( vel ); // vel es parámetro actual - Dentro de un método puede modificarse el parámetro formal (la copia), pero el parámetro actual enviado en la llamada ( vel ) se mantendrá inalterado.
168 / Paso de parámetros en Java En los métodos de Java el paso de parámetros se realiza siempre por valor . El paso de parámetros por valor consiste en copiar el contenido de la variable que se pasa en el parámetro formal (otra variable local al método) . Los parámetros que se le pasan a un método son: Tipos primitivos, que se pasan por valor. Referencias a objetos, que también se pasan por valor (las referencias no se modifican en el método). Obsérvese en este caso que, al pasar referencias, el estado del objeto pasado puede ser modificado. La referencia permite acceder a los miembros del objeto y modificar su estado.
169 Paso de referencias como parámetros Si un parámetro es una referencia a objeto, el método recibe en su parámetro formal una copia del valor de la referencia actual (dirección de memoria del objeto). Ejemplo : En la llamada a metodoEjemplo se pasa una referencia a objeto de clase Punto como parámetro. El parámetro formal p recibe una copia del valor del parámetro actual p1 (p ← p1), así que p apuntará al mismo objeto que p1 tras la llamada. 3 p 3 p1 void metodoEjemplo (Punto p){ Punto p2 = new Punto(6, 6); p.fijarX (10); p.fijarY (20); p = p2; } void main ( String args []){ Punto p1 = new Punto(3, 3); MetodoEjemplo (p1); } 10 p 20 p1 6 6 p2 6 6 p2 10 p 20 p1 6 6 p2 10 20 p1 50 50 60 50 60 50 50 60 60 50 3 3 p1 50
El método recibe una copia de la dirección de memoria del objeto, y esta apunta (o referencia) al mismo objeto que el parámetro actual. Si se modifica el valor de la copia p dentro del método, no cambiará el parámetro actual original p1 en el método de la llamada, pues fue pasado por valor. No obstante, la copia (valor de p) permite acceder al mismo objeto (que no está duplicado) y modificarlo dentro del método, y si esto se hace, el objeto al que apuntaba p1 sí quedará modificado tras finalizar el método: Si en el método se modifica el objeto apuntado por la copia de la referencia, este se mantendrá modificado a la salida del método , ya que no se ha modificado una copia del objeto sino el mismo objeto referenciado por el parámetro actual (también apuntado con la copia de la referencia). Su estado quedará modificado. Paso de referencias como parámetros
Paso de referencias como parámetros public class Punto{ // la Clase (tipo) de los objetos punto //datos o variables instancia: private int x; //coordenada x private int y; //coordenada y //métodos: public Punto( int coordX , int coordY ){ //constructor x = coordX ; // inicializa x e y y = coordY ; } public void escalar ( float e){ // escala el pto en el factor de escala e. x = x*e; y = y*e; } . . . } // end class Punto 171 public class ejemplo { // . . . clase con método main : static void escalarNubeDePuntos (Punto puntos[ ] , float magnitudEscalado ){ for ( int i = 0; i < puntos.lenght ; i++) escalarPunto ( puntos[i] , magnitudEscalado ); // NOTA: puntos[i] es un parámetro actual ref. a objeto } static void escalarPunto ( Punto p , float valorEscalado ){ p.escalar ( valorEscalado ); // p es un parámetro formal, toma como valor una copia de puntos[i], // que es una referencia a un punto. El valor del objeto referenciado // por puntos[i] queda modificado al salir de este método. } . . . // end class ejemplo Sean las dos siguientes clases del mismo paquete: Escalar Nube de puntos escalada
172 / Sobrecarga estática de los métodos En una clase de Java es posible tener dos métodos con el mismo identificador , pero con los parámetros o el tipo devuelto diferentes. Esto se conoce como sobrecargar el método. class Coche { private int velocidad; public void acelerar( int v) { velocidad += v; } public void acelerar( boolean marcha) { velocidad += 60; } } PrintStream + println () + println ( boolean ) + println ( char ) + println ( char []) + println ( double ) + println ( float ) + println ( int ) + println ( long ) + println ( Object ) + println ( String )
173 / El constructor Un constructor puede o no tener parámetros, pero no tiene valor de retorno . Su nombre siempre es el de la clase a la que pertenecen. Si no se define ningún constructor, Java añade un constructor por defecto sin parámetros. Este constructor no aparece en el código y crea el objeto. Se recomienda crear constructores. La palabra reservada new seguida del nombre de una clase y unos paréntesis con o sin parámetros invoca al constructor de la clase . El constructor es una función especial que se ejecuta cuando se crea un objeto y se usa para iniciar sus propiedades . class Coche { private boolean enMarcha ; public final int numRuedas = 4; public final static pi = 3.14; private Rueda rueda1 = new Rueda(); private int velocidad; ... public void acelerar( int incremento) { velocidad += incremento; enMarcha = true; } } … metodoExterno () { Coche c = new Coche(); System.out.println ( c.numRuedas ); System.out.println ( Coche.pi ); }
Constructor por omisión Constructor por omisión: Si no se definiese ningún constructor en la clase, Java crea uno sin argumentos que inicializa a valores por defecto: Tipos primitivos a su valor por defecto Strings y referencias a objetos a null Si se declara un constructor, este desaparece (aunque Java siempre da valores a los atributos por defecto).
175 / Varios constructores Una clase puede tener varios constructores , aunque no puede tener dos constructores que reciban los mismos parámetros. class Coche { private boolean enMarcha ; public final int numRuedas ; public final static double pi = 3.14; private int velocidad; ... public Coche( int velInicial , boolean on ){ velocidad = velInicial ; NumRuedas = 4; this ( on ); //llama al siguiente construct } public Coche( boolean on ) { enMarcha = on ; } public Coche() { } } metodoExterno () { Coche c1 = new Coche(); Coche c2 = new Coche(12, true ); Coche c3 = new Coche( true ); } En un constructor se pueden iniciar propiedades finales (final). Desde un constructor se puede llamar a otros constructores de la misma clase usando la palabra reservada this como nombre del constructor, seguida de paréntesis con los parámetros correspondientes.
Varios constructores y this en ellos public Cliente( String n, long ndni , long tel ){ this ( n,ndni ); telefono = tel ; } public Cliente( String n, long ndni ){ nombre = n; dni = ndni ; } public Cliente( String n, long ndni , long tel ){ nombre = n; dni = ndni ; telefono = tel ; }
177 / Varios constructores Las llamadas entre constructores se pueden usar cuando se desea añadir constructores con valores fijos para algunos parámetros.
178 / Invocación de miembros de otros objetos: el operador punto ‘.’ public class JuegoCoches { public static void main ( String [] args ) { Coche coche1 = new Coche(); Coche coche2 = new Coche(); Coche coche3 = c1; coche1.acelerar(10); coche2.acelerar(20); coche3.parar(); } } Para invocar a un miembro de otra clase se usa el identificador del objeto, un punto y el identificador del miembro que se desea invocar. El método reparar de la clase Coche invoca a métodos de otro objeto (un Taller). class Coche { boolean enMarcha ; int velocidad; Rueda r1 = new Rueda(); Rueda r2 = new Rueda(); Rueda r3 = new Rueda(); Rueda r4 = new Rueda(); void parar() { velocidad = 0; enMarcha = false ; } void acelerar( int incremento ) { velocidad += incremento; enMarcha = true ; } int dameVelocidad () { return velocidad; } float reparar( float dinero , Taller t ) { float precio = t.precioReparar ( this ); if (precio < dinero) { parar(); t.arreglar ( this ); return dinero - precio; } return dinero; } }
179 / Valores independientes de las propiedades public class JuegoCoches { public static void main ( String [] args ) { Coche coche1 = new Coche(); Coche coche2 = new Coche(); Coche coche3 = c1; coche1.acelerar(10); coche2.acelerar(20); coche3.parar(); } } Cada objeto tiene valores independientes para sus propiedades. El método main primero asigna valor 10 a la propiedad velocidad de un coche, luego asigna 20 a la propiedad velocidad del otro coche, finalmente asigna a cero la propiedad velocidad del primero . class Coche { boolean enMarcha ; int velocidad; Rueda r1 = new Rueda(); Rueda r2 = new Rueda(); Rueda r3 = new Rueda(); Rueda r4 = new Rueda(); void parar() { velocidad = 0; enMarcha = false ; } void acelerar( int incremento) { velocidad += incremento; enMarcha = true ; } int dameVelocidad () { return velocidad; } }
180 / Invocación de miembros del propio objeto Para hacer referencia a un miembro (método o propiedad) de la propia clase se usa simplemente el identificador de dicho miembro. public class JuegoCoches { public static void main ( String [] args ) { Coche coche1 = new Coche(); Coche coche2 = new Coche(); Coche coche3 = c1; coche1.acelerar(10); coche2.acelerar(20); coche3.parar(); } } class Coche { boolean enMarcha ; int velocidad; Rueda r1 = new Rueda(); Rueda r2 = new Rueda(); Rueda r3 = new Rueda(); Rueda r4 = new Rueda(); void parar() { velocidad = 0; enMarcha = false ; } void acelerar( int incremento) { velocidad += incremento; enMarcha = true ; } int dameVelocidad () { return velocidad ; } }
Desde la clase Taller es necesario invocar a los métodos de la Clase Coche precedidos del objeto que envía el mensaje (objeto invocante) seguido del operador ‘.’. Desde la clase Coche donde está definido el método no (líneas en rojo). Invocación de métodos miembro Otro ejemplo public class Coche { // datos: private int numAlfombrillas ; private String color; // métodos: . . . public void pintarCoche ( String c){ color = c; } public void puestaAPuntoVenta () { numAlfombrillas = 4; pintarCoche (“blanco”); } . . . } public class Taller { // datos: private Coche cocheSustitucion1, cocheSustitucion2; . . . // métodos: . . . void Taller(){ // constructor cocheSustitucion1 = new Coche(); cocheSustitucion2 = new Coche(); } public void mantenimiento() { cocheSustitucion1.pintarCoche(“blanco”); cocheSustitucion2.pintarCoche(“azul”); } . . . } Otro ejemplo
182 / Las clases Parámetros class Coche { boolean enMarcha ; int velocidad; Rueda r1 = new Rueda(); Rueda r2 = new Rueda(); Rueda r3 = new Rueda(); Rueda r4 = new Rueda(); void parar() { velocidad = 0; enMarcha = false ; } void acelerar( int incremento ) { velocidad += incremento; enMarcha = true ; } int dameVelocidad () { return velocidad; } float reparar( float dinero , Taller t ) { float precio = t.precioReparar ( this ); if (precio < dinero) { parar(); t.arreglar ( this ); return dinero - precio; } return dinero; } } public class JuegoCoches { public static void main ( String [] args ) { Coche coche1 = new Coche(); Coche coche2 = new Coche(); Coche coche3 = c1; coche1.acelerar(10); coche2.acelerar(20); coche3.parar(); } } A los métodos se les pueden pasar tipos primitivos u otros objetos. Por ejemplo, podemos añadir la clase Taller que cambia las ruedas del coche.
183 / Las clases Interior de los métodos La palabra reservada this sirve para referirnos al propio objeto (el que llamó al método). Por ejemplo, para que el coche pueda pasarse el mismo al taller. class Coche { boolean enMarcha ; int velocidad; Rueda r1 = new Rueda(); Rueda r2 = new Rueda(); Rueda r3 = new Rueda(); Rueda r4 = new Rueda(); void parar() { velocidad = 0; enMarcha = false ; } void acelerar( int incremento) { velocidad += incremento; enMarcha = true ; } int dameVelocidad () { return velocidad; } float reparar( float dinero , Taller t) { float precio = t.precioReparar ( this ); if (precio < dinero) { parar(); t.arreglar ( this ); return dinero – precio; } return dinero; } } public class JuegoCoches { public static void main ( String [] args ) { Coche coche1 = new Coche(); Coche coche2 = new Coche(); Coche coche3 = c1; coche1.acelerar(10); coche2.acelerar(20); coche3.parar(); } }
184 / Las clases Control de acceso a los miembros Por defecto, si no se escribe modificador de acceso, el miembro es friendly : visible desde las clases que pertenezcan al mismo paquete (directorio) e inaccesible desde fuera del paquete. Los modificadores de control de acceso más habituales en Java son: public : permite acceder al miembro desde fuera de la clase. private : no permite acceder al miembro desde fuera de la clase. Las propiedades suelen ser siempre privadas. Los métodos privados suelen corresponder a funciones auxiliares. class Coche { private int velocidad; Rueda r1 = new Rueda(); Rueda r2 = new Rueda(); Rueda r3 = new Rueda(); Rueda r4 = new Rueda(); public void acelerar() { incrementarExponencial (); } private void incrementarExponencial () { for ( int cont = 0; cont < 100; cont ++) velocidad += cont ; } } Visibilidad Modificador Clase Paquete Todos public Sí Sí Sí sin modificador Sí Sí No private Sí No No
185 / Clases públicas Una clase con modificador public indica que la clase es visible desde otros paquetes diferentes al paquete en el que se implementa. Por el contrario, una clase no definida pública sólo es visible en el paquete en el que se implementa. Solo puede existir una clase pública por fichero y el nombre de tal clase debe coincidir con el nombre del fichero. class Rueda { private int radio = 3; ... } public class Coche { private Rueda r = new Rueda(); ... }
186 / Clases internas y clases internas privadas Una clase interna es una clase que se define anidada dentro de otra. Una clase interna definida private solo es visible dentro de la clase en la que está definida. public class Stack { private class Node { Node next; int value; } private Node top = new Nodo(); ... } public class Coche { class Rueda { private int radio = 3; ... } // end class Rueda private Rueda r = new Rueda(); ... } // end class Coche
187 / Las clases Todo junto en un ejemplo public class Coche { class Rueda { private int presion = 2000; private float radio = 6.28f; public float dameRadio () { return radio; } public void subePresion () { presion += 10; } } private boolean enMarcha ; private int velocidad; private Rueda ruedaRepuesto = new Rueda(); /** Fren el coche en seco */ public void parar() { velocidad = 0; enMarcha = false ; } } /** @return devuelve la rueda de repuesto */ public Rueda dameRueda () { return ruedaRepuesto ; } /** Método que aumenta la velocidad * @param incremento Valor que se suma a velocidad */ public void acelerar( int incremento) { velocidad += incremento; enMarcha = true ; } /** Lleva el coche al taller * @param dinero disponible para reparación */ public float reparar( float dinero , Taller t){ float precio = t.precioReparar ( this ); if (precio < dinero) { parar(); t.arreglar ( this ); } return dinero - precio; } } public class Taller { /** @param c Coche a ser reparado. * @return presupuesto de la reparación */ public float precioReparar (Coche c) { return 100 * c.dameRueda (). dameRadio (); } /** Repara el coche. * @param c Coche a ser reparado.*/ public void arreglar(Coche c) { c.dameRueda (). subePresion (); } } public class JugandoConCoches { public static void main ( String [] args ) { Coche c = new Coche(); Taller t = new Taller(); c.reparar (1000f, t); } }
188 / Detalles de las propiedades En esta sección se profundiza en el concepto de propiedad.
189 / Propiedades privadas Normalmente las propiedades de los objetos se mantienen privadas . Si se desea que una propiedad privada sea consultada o modificada desde fuera de la clase se suelen añadir métodos públicos getters y setters . Los getters y setters permiten consultar o modificar variables privadas de forma controlada. class Coche { private int speed ; public int getSpeed () { return speed ; } public void setSpeed ( int speed ) { if ( speed > 120) this .speed = 120; else if ( speed < 0) this .speed = 0; else this .speed = speed ; } }
190 / Propiedades final final es un modificador que se usa para indicar que el valor de una propiedad no va a cambiar. Así, las propiedades final son constantes a lo largo de la vida del objeto. Su valor puede definirse en compilación o en ejecución. Las referencias a objetos declaradas final no pueden cambiarse, aunque los objetos en sí mismos pueden cambiar su estado. Una variable final de tipo primitivo, por su carácter inmutable, puede decidirse declararla pública. class Coche { private boolean enMarcha ; public final int numRuedas = 4; private final Rueda r = new Rueda(); ...
Constantes - final La palabra reservada final indica que su valor no puede cambiar Si se define como final : Una clase N o puede tener clases hijas (seguridad y eficiencia del compilador) Un método N o puede ser redefinido por una subclase Una variable T iene que ser inicializada al declararse (o en el constructor/es) y su valor no puede cambiarse En atributos suele combinarse con static . El identificador de una variable final debe escribirse en mayúsculas (es una constante)
192 / Propiedades de objeto o de clase Se pueden distinguir dos tipos de propiedades: Propiedades de objeto. Se pueden consultar en los objetos que se creen de esa clase. Propiedades de clase (o estáticas ). Se pueden consultar sobre la propia clase. Las propiedades estática son compartidas por todos los objetos de la clase (comparten valor). Para indicar que una propiedad es estática se usa el modificador de uso static (en UML se subrayan). final puede usarse combinado con static para definir propiedades constantes para todos los objetos de una clase. class Coche { //Propiedades de los objetos private boolean enMarcha ; public final int numRuedas = 4; //Propiedad de la clase public final static double pi=3.14; }
Constantes – final - Ejemplo public class MiClase { final int NUEVO_ARCHIVO = 3; void f(){ NUEVO_ARCHIVO = 27; } } public class MiClase { final int NUEVO_ARCHIVO; public MiClase() { NUEVO_ARCHIVO=27; } } ERROR O.K.
194 / Para acceder a las propiedades de clase desde fuera de la clase se utiliza el nombre de la clase, o de una referencia a un objeto, seguido del nombre de la propiedad separados por un punto. Acceso a las propiedades de clase class Coche { private boolean enMarcha ; public final int numRuedas = 4; private Rueda r = new Rueda(); public final static double pi = 3.14; void acelerar( int incremento) { velocidad += incremento; enMarcha = true; } } … Coche coche = new Coche(); System.out.println ( c.numRuedas ); System.out.println ( Coche.pi ); System.out.println ( c. pi );
195 / Los paquetes Forma de crear y acceder a los paquetes en Java.
196 / Definición de paquetes en Java Las clases en Java se organizan en ficheros y los ficheros en Paquetes. Java define una correspondencia entre los directorios , que contienen físicamente a los ficheros, y los paquetes que los contienen lógicamente. Java permite organizar en forma de árbol los paquetes gracias al uso de los directorios de ficheros.
197 / Los paquetes Declaración de paquetes La pertenencia de un fichero a un paquete se declara en la primera línea de código del fichero usando la palabra reservada package seguida del nombre del paquete y ;. Los nombres de los paquetes se suelen escribir en minúsculas. El anidamiento de paquetes en Java se representa usando el punto como separador de los sucesivos paquetes del árbol de paquetes. Abajo, el paquete automovilismo pertenece al paquete útil, y el paquete útil pertenece al paquete urjc . La clase Parking pertenece al paquete automovilismo . Desde otra clase, esta se puede escribir con el nombre completamente calificado urjc.util.automovilismo.Parking , o bien se puede evitar escribir el nombre completamente calificados realizando import urjc.util.automovilismo ; package urjc.util.automovilismo ; public class Parking { Coche c = new Coche(); Camion c1 = new Camion (); v ehiculos.agricolas.Tractor = new vehiculos.agricolas.Tractor(); }
198 / Los paquetes Acceso a un paquete desde otro Para acceder a una clase definida en un fichero se puede usar su nombre completamente calificado , que consiste en separar con puntos los nombres ordenados de toda la rama de paquetes hasta el tipo. Se puede utilizar la palabra reservada import al principio de un fichero para evitar usar nombre completamente calificados para acceder a una clase. package urjc.util.automovilismo ; import vehiculos.utilitarios.Coche ; import vehiculos.camiones.*; public class Parking { Coche c = new Coche(); // no requiere toda la ruta Camion c1 = new Camion (); // no requiere toda la ruta v ehiculos.agricolas.Tractor t = new vehiculos.agricolas.Tractor(); }
199 / Visibilidad de los elementos de un paquete Dentro de un paquete se comparten los elementos friendly . No se puede acceder a los elementos friendly de otro paquete aunque exista relación de anidamiento.
Paquetes ( packages ) Un paquete en Java ( package ) es un conjunto de clases definidas en un subdirectorio común. Para definir un paquete, se escribe la sentencia: package nombre_paquete ; en la primera línea de cada clase del paquete. Ejemplo de paquete llamado escritorio con 3 archivos: El subdirectorio que contiene al paquete debe llamarse igual que el paquete. P.e. Los ficheros Lapiz.java, Boligrafo.java y Folio.java se ubicarán en el subdirectorio escritorio. // archivo Boligrafo.java package escritorio; public class Boligrafo { // ... miembros de la clase // ... } //archivo fuente Lapiz.java package escritorio; public class Lapiz { //... miembros de la clase // ... } // archivo Folio.java package escritorio; public class Folio { // ...miembros de la // clase ... } 200
Paquetes ( packages ) Para usar una clase situada en otro paquete distinto al actual, puede escribirse al principio del fichero actual la palabra clave import seguida de las clases externas o de los paquetes externos que se desean incluir. Para indicar una clase que se encuentra en un paquete externo, se escribe a continuación de la sentencia package , el nombre del paquete donde está, seguido del selector punto “.” y a continuación el nombre de la clase. import nombre_paquete.nombreClase ; 201
Paquetes ( packages ) Ejemplo: package proyectofisica ; import ta.medidas.Termometro ; //importa la clase Termometro //del paquete ta.medidas import ta.medidas.Escala ; //importa la clase Escala del paquete // ta.medidas // con estas líneas al principio, se importan esas clases y // ya se pueden usar esos identificadores de clases para // instanciar objetos de esas clases y llamar a sus métodos. Ejemplo : puede importarse un paquete completo (con todas sus clases) así: import nombrePackage.*; //importa todas las clases del // paquete nombrePackage . Aunque aparezca esta sentencia, el compilador genera bytecode sólo para las clases utilizadas en el programa . 202
Paquetes ( packages ) Si dos paquetes importados tienen clases que se llaman igual, hay que indicar el paquete que contiene a cada una de las clases cuando esta se va a nombrar.Ej : Sean los paquetes cocina y pescaderia que contienen una clase Mejillon cada uno. Si importamos ambos y usamos la clase Mejillon , es preciso especificar el paquete de la clase a la que nos referimos. Si no se indica el paquete, dará un error por clase ambigua. package alimentacion ; import cocina.Mejillon ; //importa la clase Mejillon del package cocina. import pescaderia.Mejillon ;// importa la clase Mejillon del package pescaderia cocina.Mejillon m = new cocina.Mejillon (“fresco”); pescaderia.Mejillon mej = new pescaderia.Mejillon (“purpura”); 203
Paquetes Convenio para el nombrado de paquetes : Ejemplo: urjc.die.bmoreno.poo Un paquete determina un subdirectorio del disco En el ejemplo anterior: urjc /die/ bmoreno / poo /
Paquetes import “.*” permite importar todas las clases e interfaces de un paquete import java.util .*; // todas las clases de util import java.*; // ERROR: no vale para paquetes Ejemplo: Para importar la clase ArrayList , hay dos posibilidades: import java.util.ArrayList ; // directamente la clase import java.util .*; // todas las clases del paquete