Módulo 1 Fundamentals of the Java Programming Language
Profesional en Plataforma
JAVA
Contenido Introducción y Objetivos ........................................................................................................................................................... 1 Unidad 1. Entendiendo la tecnología Java ................................................................................................................................. 2 ¿Qué son los objetos?................................................................................................................................................... 2 Clases, Mensajes y Métodos ....................................................................................................................................... 3 Unidad 2. Analizando un problema y diseñando una solución ................................................................................................... 6 Analizar un problema usando análisis orientado a objetos .............................................................................. 6 Diseño de clases para crear objetos ...................................................................................................................... 10 Unidad 3. Desarrollando y probando programas con tecnología JAVA .................................................................................... 12 Instalación y configuración del kit de desarrollo de Sun (JDK) .................................................................... 12 Procesos para crear un programa en Java .......................................................................................................... 15 Unidad 4. Declarando, Inicializando y usando variables .......................................................................................................... 20 Elementos básicos del lenguaje y sintaxis de Java ........................................................................................... 20 Alcance de las variables ............................................................................................................................................. 24 Declarando variables .................................................................................................................................................. 26 Conversión entre tipos (casting) ............................................................................................................................. 30 Laboratorio: Casting entre tipos de datos. ........................................................................................................ 33 Unidad 5. Creando y usando Objetos ...................................................................................................................................... 35 Declarar, instanciar e inicializar variables de referencia de objeto ............................................................. 35 La clase String .............................................................................................................................................................. 41 Introducción a los flujos o streams ........................................................................................................................ 44 Laboratorio: Validación Email................................................................................................................................. 46 Unidad 6. Usando operadores y constructores........................................................................................................................ 49 Operadores y expresiones......................................................................................................................................... 49 Operadores Aritméticos (Suma, resta, multiplicación, división, resto, incremento y decremento). 50 Operadores Relacionales. .......................................................................................................................................... 50 Operadores Condicionales. ....................................................................................................................................... 51 Operadores a nivel de bit .......................................................................................................................................... 51 Operadores de asignación. ....................................................................................................................................... 51 Operador ternario if-then-else ................................................................................................................................. 52 Sentencias de excepción, bloques try, catch, finally. ...................................................................................... 53 Laboratorio: Averiguar día de nacimiento de la semana. ............................................................................... 56 Unidad 7. Usando Loops ......................................................................................................................................................... 60 Sentencia if-else ........................................................................................................................................................... 60 Sentencia switch-case ................................................................................................................................................ 61 Sentencia while............................................................................................................................................................. 62
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Sentencia do-while ...................................................................................................................................................... 63 Sentencia for ................................................................................................................................................................. 64 Laboratorio: Conjetura Collatz................................................................................................................................. 66 Unidad 8. Desarrollando y usando métodos ............................................................................................................................ 69 Métodos (Funciones Miembro) ................................................................................................................................. 69 Laboratorio: Creación del objeto Calculadora..................................................................................................... 77 Unidad 9. Implementando encapsulación ............................................................................................................................... 83 Paquetes ......................................................................................................................................................................... 83 Modificadores de ámbito ............................................................................................................................................ 85 Laboratorio: Creación y uso de paquetes. ........................................................................................................... 91 Unidad 10. Creando y usando arreglos .................................................................................................................................... 95 Concepto de Array ....................................................................................................................................................... 95 Arrays Unidimensionales ........................................................................................................................................... 95 Arrays Multidimensionales ........................................................................................................................................ 99 Colecciones .................................................................................................................................................................. 103 Colección Set ............................................................................................................................................................... 105 Colección List ............................................................................................................................................................... 107 Colección Map ............................................................................................................................................................. 108 Laboratorio: Temperaturas Anuales .................................................................................................................... 108 Unidad 11. Implementando herencia .................................................................................................................................... 111 Herencia ........................................................................................................................................................................ 111 Laboratorio: Proyecto clases agenda................................................................................................................... 117
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Introducción y Objetivos
1
Introducción Java es un lenguaje de programación con el que podemos realizar cualquier tipo de desarrollo. Java fue desarrollado por la compañía Sun Microsystems y está enfocado a cubrir las necesidades tecnológicas de empresas. Uno de los conceptos más interesantes de la tecnología Java es que es un lenguaje independiente de la plataforma. Esto quiere decir que si hacemos un programa en Java podrá funcionar en cualquier ordenador del mercado independientemente del sistema operativo en el que vayamos a utilizar el desarrollo. Esta es la mayor ventaja de Java respecto a sus máximos competidores en lenguajes de programación y simplifica el trabajo del programador, pudiendo centrarse en un único desarrollo independiente de la plataforma dónde vaya a utilizarse dicho desarrollo. Esta capacidad del lenguaje Java se consigue por la Máquina Virtual de Java. La máquina virtual de Java hace de puente entre el sistema operativo y el programa de Java y permite que el sistema operativo comprenda todo tipo de desarrollo. Otra de las características del lenguaje Java son sus múltiples tipos de desarrollos. Existen diferentes soluciones para los dispositivos dónde se vaya a implementar cada solución, como pueden ser móviles, agendas y en general, cualquier dispositivo que la tecnología permita.
Objetivo Explicar las características del lenguaje de programación JAVA.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 1. Entendiendo la tecnología Java Introducción Java es un lenguaje que utiliza P.O.O (Programación orientada a objetos), dicho concepto se basa en el modelo objeto, donde el elemento principal es el objeto, el cual es una unidad que contiene todas sus características y comportamientos en sí misma, lo cual lo hace como un elemento independiente, pero que se interrelaciona con objetos de su misma clase o de otras clases, como sucede en el mundo real.
Objetivo Comprender el concepto y características del lenguaje de programación Java.
¿Qué son los objetos? Para aprender la relación entre objetos del lenguaje de programación Java debemos abstraernos y pensar en términos ajenos a la programación, utilizando elementos de la vida real. Un objeto es una persona, animal o cosa. La forma de distinguir cualquier objeto de otro es por unas determinadas características y su utilidad como objeto para realizar unas acciones que no puede realizar otro objeto diferente. Pongamos como ejemplo que no es lo mismo utilizar un coche que una televisión, siendo los dos objetos, pero la clase de cada uno define sus acciones y propiedades para lo que ha sido creado. Pues esto mismo es lo que realiza el lenguaje Java. Cada objeto está pensado para realizar una serie de acciones y dependiendo de nuestra lógica que deseemos aplicar, utilizaremos un objeto u otro de una clase diferente. Utilizando el ejemplo del coche y la televisión. Un coche es un objeto. Tiene como características o propiedades el número de puertas, la velocidad máxima, el color, la cilindrada, la altura o el peso. Y también tiene una serie de acciones que podemos realizar sobre un coche, tales como arrancar, frenar, girar, acelerar, cambiar de marcha, mover respaldo o abrir puertas. Cada objeto se define en función de multitud de propiedades y se pueden realizar innumerables operaciones sobre él. Los objetos pueden interactuar entre sí o utilizarlos de forma única. Una televisión tiene otras características y acciones totalmente diferentes a un coche. Podemos utilizar tanto un coche como una televisión de forma independiente. El coche para conducir y la televisión para visualizar películas o series. Cada uno tiene su función específica. Pero también puedo combinar los dos objetos para poner una televisión portátil en el coche. De esa forma, estoy combinando dos objetos diferentes para conseguir una funcionalidad específica en mi lógica: Visualizar películas en el coche. Todos estos conceptos son la base de cualquier lenguaje de programación orientado a objetos, y es lo que aprenderemos en el curso. En términos de programación, la misión del programador será determinar qué propiedades y operaciones interesa utilizar sobre un objeto. Por ejemplo, sobre el objeto coche pudiera ser que no necesitemos bajar la ventanilla en un viaje, por lo que no será necesario que apliquemos dicha funcionalidad sobre el objeto cuando lo utilicemos. Dependiendo de la acción para la que hemos pensado utilizar el objeto, utilizaremos unas funciones o propiedades u otras. Aunque el objeto tenga mil acciones, nosotros pensaremos cuales son las que nos convienen en cada momento y cuales no. En terminología de programación orientada a objetos (P.O.O), las características del objeto se les denomina propiedades y a las acciones métodos. Cada uno de estos métodos es un procedimiento o una función perteneciente a un objeto. Un objeto está formado por una serie de características o datos (propiedades) y una serie de operaciones (métodos). No puede utilizarse únicamente en función de los datos o de las operaciones sino en su conjunto.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Clases, Mensajes y Métodos En la programación orientada a objetos (POO) tenemos que diferenciar entre dos conceptos estrechamente relacionados: la clase y el objeto. Una clase define la forma y comportamiento de un objeto. Una clase es una plantilla para un objeto. Define la estructura de un objeto y su interfaz funcional, en forma de métodos y propiedades. Cuando se ejecuta un programa en Java, el sistema utiliza definiciones de clase para crear instancias de las clases, que son los objetos reales. Los términos instancia y objeto se utilizan de manera indistinta. public class Coche { DECLARACION DE METODOS Y PROPIEDADES } De este modo se definiría una clase de nombre Coche cuyas propiedades y métodos son definidos en su interior. Las características y acciones de una clase son las propiedades y métodos declarados en su interior y de los que van a disponer todos los objetos o instancias de la misma. Las propiedades o miembros del objeto coche, definirían todos los datos que podemos recuperar o utilizar en un objeto. Son variables definidas dentro del objeto y que nos permiten luego “utilizar” dichas variables en nuestro programa. public class Coche { public int velocidad; public int numeropuertas; } Los métodos son las acciones que un objeto nos permitiría realizar sobre él. Existen dos tipos de métodos que posteriormente aprenderemos en profundidad, métodos que devuelven valor y métodos de acción. Los métodos de acción son métodos que no devuelven ningún tipo de información, son un conjunto de acciones, y se definen con la palabra clave void. Los métodos que devuelven valor (también llamados funciones), son métodos que realizan una serie de acciones y que devuelven un valor cómo resultado de dichas acciones. Un ejemplo de ello sería: public class Coche { public int velocidad; public int numeropuertas; public void arrancarCoche() { ARRANCAR EL COCHE Y NO DEVUELVE NADA } public int acelerarCoche() { DEVOLVER VELOCIDAD ACTUAL } } Cuando utilizamos el método acelerarCoche() es conveniente saber la velocidad a la que hemos acelerado, por lo que devolveríamos información sobre el objeto. El método arrancarCoche() no devuelve ningún valor porque es una acción de la que no necesitamos saber ningún tipo de información.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Un objeto es una variable que utiliza las características y acciones de un objeto. Dependiendo de la clase de la variable, tendrá unas características u otras. A estas variables se las conoce como referencias a objeto. Si quisiéramos utilizar un objeto de la clase Coche, primero habría que “crearla”, o mejor dicho, instanciar un objeto de la clase PrimeraClaseJava. Para ésta creación de un objeto se utiliza el constructor de una clase. Las clases pueden implementar un método especial llamado constructor. Un constructor es un método que inicia un objeto inmediatamente después de su creación. De esta forma nos evitamos el tener que iniciar las variables explícitamente para su iniciación. El constructor tiene exactamente el mismo nombre de la clase que lo implementa; no puede haber ningún otro método que comparta su nombre con el de su clase. Una vez definido, se llamará automáticamente al constructor al crear o instanciar un objeto de esa clase (al utilizar el operador new). El constructor no devuelve nada, es una acción. Su misión es iniciar o construir todo estado interno de un objeto (sus propiedades), haciendo que el objeto sea utilizable inmediatamente; reservando memoria para sus propiedades, iniciando sus valores, etc. Ejemplo: public class Coche { public Coche() { velocidad = 0; numeropuertas = 5; } public int velocidad; public int numeropuertas; public void arrancarCoche() { velocidad = 0; } public int acelerarCoche() { velocidad = velocidad + 10; } } Lo que acabamos de crear es una clase para la que todos sus objetos creados tendrán 5 puertas. El operador new crea una instancia de una clase (un objeto) y devuelve una referencia a ese objeto. Por ejemplo: Coche objetocoche1 = new Coche(); De ésta forma, el objeto es nuestra variable llamada objetocoche1 y sabemos que tiene 5 puertas porque hemos “construido” la clase Coche de esa forma. Si utilizásemos el objetocoche1 para averiguar el número de puertas, siempre nos devolvería el número 5. mostrar objetocoche1.numeropuertas dicha instrucción siempre mostraría 5 También podemos cambiar las características de nuestro objeto de la clase Coche y establecer un número de puertas diferente: objetocoche1.numeropuertas = 3; mostrar objetocoche1.numeropuertas dicha instrucción ahora mostraría 3
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Podemos crearnos otros objetos de la clase utilizando otras instancias de objeto, de esa forma, se crean objetos con las mismas características, pero diferentes entre sí. Coche objetocoche1 = new Coche(); Coche objetocoche2 = new Coche(); objetocoche1.numeropuertas = 3; mostrar objetocoche1.numeropuertas dicha instrucción ahora mostraría 3 mostrar objetocoche2.numeropuertas dicha instrucción siempre mostraría 5 Como podemos comprobar, los dos objetos pertenecen a la misma clase y tienen las mismas propiedades y métodos, pero son diferentes entre sí. Aunque no hubiésemos cambiado el atributo numeropuertas, seguirían siendo objetos diferentes, con las mismas características y métodos. Llevado al concepto de la vida real, sería como sacar dos coches iguales de la fábrica, tienen los mismos atributos, color, cilindrada, modelo, pero cada uno es diferente y cada uno se utilizará de una forma diferente.
Ver Video: Tecnología Java , en la Unidad 1, en el Módulo 1, en la plataforma elearning Actividades “Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades que encontrará en la unidad correspondiente de la plataforma eLearning”.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 2. Analizando un problema y diseñando una solución Introducción Dentro de cualquier lógica en un programa podemos encontrarnos con diferentes formas de plantear una solución. Con la tecnología Java, existen una serie de características que nos pueden ayudar a simplificar el problema. La programación orientada a objetos permite simplificar la estructura de elementos en una aplicación, implementando los diferentes tipos de soluciones y llegando a un nivel mucho más óptimo en el momento de construir el análisis que nos llevará a completar la aplicación.
Objetivos
Conocer los objetivos de las aplicaciones Java.
Introducir al usuario en la programación orientada a objetos, mostrando sus características y cómo pueden ayudarnos a solucionar un problema lógico dentro del lenguaje Java.
Analizar un problema usando análisis orientado a objetos Java es un lenguaje considerado Orientado a Objetos (P.O.O). Todo lenguaje orientado a objetos tendrá las siguientes características:
HERENCIA ENCAPSULACION POLIMORFISMO ABSTRACCION
Antes de empezar a estudiar en detalle el lenguaje Java, es imprescindible conocer los conceptos y características particulares de la programación orientada a objetos (POO). Éste punto es importante porque define cualquier lenguaje que utiliza POO. La programación orientada a objetos es una evolución lógica de la programación estructurada, en la que el concepto de variables locales a un procedimiento o función, que no son accesibles a otros procedimientos y funciones, se hace extensible a los propios subprogramas que acceden a estas variables. Pero la programación orientada a objetos va mucho más allá. En realidad, cambia la concepción de la metodología de diseño de los programas. En la programación orientada a objetos, se definen objetos que conforman una aplicación. Estos objetos están formados por una serie de características y operaciones que se pueden realizar sobre los mismos. Estos objetos no están aislados en la aplicación, sino que se comunican entre ellos.
Herencia Es una de las principales ventajas de la POO. Esta característica permite definir clases descendentes a partir de otras, de forma que la nueva clase (la clase descendente) hereda de la clase antecesora todas sus propiedades y métodos. La nueva clase puede definir nuevas propiedades y métodos, además puede redefinir propiedades y métodos ya existentes. Es la forma natural de definir objetos en la vida real. Si nos posicionamos en el ejemplo de la clase Coche, podremos visualizar las ventajas de utilizar herencia. En la vida real, todo coche tiene las mismas características: ruedas, puertas, asientos, www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
velocidad, marchas, cilindradas. También todo coche tiene las mismas acciones: arrancar, frenar, acelerar, girar, cambiar marchas, etc. Hasta ahí podemos definir cualquier vehículo que podamos pensar. Tenemos un coche “base” o inicial, pero existen multiples tipos de coche, todo terrenos, utilitarios, deportivos, formula 1, etc. Para crearnos un 4X4, debemos utilizar las mismas características de un coche y cambiarlo o implementarlo para adaptarlo al nuevo tipo de vehículo. Los ingenieros que vayan a diseñar el 4X4 no vuelven a investigar la creación de un coche desde cero, pensando en cómo arrancar o frenar, sino que utilizan la tecnología ya creada del coche para “mejorarlo”, utilizando todo lo que tiene un coche y añadiendo características a su nuevo objeto. No comienzan desde cero, sino que ya tienen una base desde la que trabajar. Ese es el concepto de Herencia en POO. Vemos el concepto desde el ejemplo anterior de la clase Coche, incluyendo una propiedad llamada velocidadmaxima: public class Coche { public Coche() { velocidad = 0; numeropuertas = 5; velocidadmaxima = 180; } public int velocidad; public int velocidadmaxima; public int numeropuertas; public void arrancarCoche() { velocidad = 0; } public int acelerarCoche() { velocidad = velocidad + 10; } } En el constructor de la clase hemos definido que la nueva propiedad velocidadmaxima será de 180, de forma que cualquier Coche podrá acelerar, arrancar, mostrar la velocidad o un número de puertas. Si deseamos crearnos un deportivo, podemos afirmar correctamente que un deportivo es un Coche, por lo que no tenemos que volver a definir las características del coche ni tenemos que volver a escribir sus métodos. Bastaría con comenzar desde nuestra clase Coche y mejorarlo: public class Deportivo: Coche { public int numeromarchas; public Deportivo () { numeromarchas = 7; velocidadmaxima = 270; } } Los dos puntos a continuación del nombre de la clase indican que la clase Deportivo hereda de la clase Coche, lo que quiere decir que un deportivo tendrá las mismas características que un coche, pero con una velocidad máxima superior. Además nos hemos creado una propiedad que indica que un Deportivo contiene siete marchas. Con todo éste concepto lo que podemos afirmar que un Deportivo es un Coche, pero mejorado. www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Encapsulación La encapsulación consiste en la propiedad que tienen los objetos de ocultar sus propiedades o los métodos, a otras partes del programa u otros objetos. La forma natural de construir una clase es la de definir una serie de características que, en general, no son accesibles fuera del mismo objeto, sino que únicamente pueden modificarse a través de los métodos que son definidos como accesibles desde el exterior de esa clase. En realidad, el concepto de encapsulación se puede definir coloquialmente como “no permitir visualizar características del objeto que no deseo que sean utilizadas”. A modo de mundo real, podemos pensar en un coche. Cualquier coche nos permite utilizar una serie de características para su funcionamiento, tales como arrancar o frenar. Pero si queremos realizar algunas acciones sobre un coche, tenemos que ponernos en contacto con el fabricante o el taller mecánico constructor del coche, ya que no son “accesibles” para utilizar el coche. Por ejemplo, el motor de un coche no es “accesible” a nosotros como conductores, si queremos realizar acciones como cambiar la correa de distribución, dicha característica está dentro del coche, pero no ha sido “expuesta” para que nosotros la manejemos, sino que forma parte del coche pero está oculta a nuestros ojos. Para poder encapsular propiedades o métodos dentro del lenguaje Java se utilizan las palabras clave public o prívate entre otras, pero que nos servirán para aprender el concepto en estos momentos.
public: indica que una propiedad o método será accesible y será visualizada al acceder al objeto.
private: indica que una propiedad o método sólo será “visible” desde el propio objeto, impidiendo que sea utilizada por otros objetos.
Podemos poner como ejemplo la misma clase Coche anteriormente utilizada en nuestra explicación. public class Coche { public int velocidad; private int Motor; public void arrancarCoche() { } private void cambiarCorreaDistribucion() { } } Según acabamos de escribir en nuestra clase, cualquier objeto que instanciemos de la clase Coche podrá utilizar el método arrancarCoche() y la propiedad velocidad, pero no podrá utilizar el método cambiarCorreaDistribucion() ni la propiedad Motor. Esto se debe a que son propiedades o métodos que no deseamos que alguien que utiliza nuestro objeto sea capaz de modificar o utilizar. De forma que si ahora intentamos utilizar las acciones, nos aparecería una excepción al compilar la clase: Coche objetocoche1 = new Coche(); mostrar objetocoche1.velocidad _ nos permitiría visualizar la velocidad del objeto) objetocoche1.arrancarCoche(); Nos permite acceder al método del objeto) mostrar objetocoche1.Motor _ Excepción porque no es accesible esa propiedad, está encapsulada en la clase Coche.) objetocoche1.cambiarCorreaDistribucion(); _ Excepción porque no es accesible el método,_ www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
está encapsulado en la clase Coche y sólo podemos utilizarlo _ dentro del código de dicha clase.)
Polimorfismo El polimorfismo permite que un mismo mensaje enviado a objetos de clases distintas haga que estos se comporten también de forma distinta, objetos distintos pueden tener métodos con el mismo nombre o incluso un mismo objeto puede tener nombres de métodos idénticos pero con distintos parámetros o acciones. Si lo llevamos a la vida real, podemos comprobar fácilmente el concepto. Dos objetos de clases diferentes tienen el mismo nombre de método, pero al realizar la “misma” acción sobre ellos, se comportan de forma diferente dependiendo del objeto. Por ejemplo, una ventana tiene la acción “abrir” y un fichero de un sistema operativo también tiene la función “abrir”, pero todos sabemos perfectamente que no es lo mismo abrir un fichero que abrir una ventana, es la misma acción aplicada a objetos de clases diferentes y que cada uno se comporta o se utiliza de una forma diferente. También existe el polimorfismo aplicado a un mismo objeto, el concepto es sencillo, misma acción sobre un objeto, pero que dependiendo de las acciones que realicemos sobre el método, se comporta de una forma o de otra totalmente distinta o similar. Por ejemplo, podemos pensar en el pedal del freno de un coche, no es lo mismo frenar a tope, que frenar poco a poco. Dependiendo como accionemos el pedal del freno, el coche se comporta de una forma diferente, siendo la misma acción sobre el objeto. No se ponen varios pedales para el freno (uno para cada tipo de frenada), sino que se utiliza la misma acción de formas diferentes. Eso es polimorfismo, la sobrecarga de un método con el mismo nombre, pero con diferentes paramétros. Podemos verlo claramente en nuestro ejemplo: public class Coche { public int velocidad; public void frenarCoche() { velocidad = velocidad – 10; } public void frenarCoche(int presion) { velocidad = velocidad – presion; } } En nuestro ejemplo hemos sobrecargado del método frenarCoche(). Tenemos dos métodos con el mismo nombre, pero la acción será diferente dependiendo del valor que le enviemos al método. Coche objetocoche1 = new Coche(); objetocoche1.frenarCoche() _ ésta acción reducirá la velocidad del vehículo en 10 objetocoche1.frenarCoche(30) es la misma acción de frenar, pero en éste caso,_ frenará la velocidad del coche en 30.
Abstracción La abstracción consiste en aislar un elemento de su contexto o del resto de los elementos que lo acompañan hasta encontrar similitudes con otros mismos objetos de su entorno. Con todo objeto podemos abstraernos hasta encontrar similitudes con otro objeto, para definirlo o localizarlo. Por ejemplo, un barco y un coche no tienen ningún elemento en común al mismo nivel, el barco es un objeto creado para ser utilizar en agua y navegar, mientras que un coche está creado para ser www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
utilizado en tierra y conducir. Pero si nos abstraemos, podemos ser capaces de encontrar similitudes entre los dos objetos, no al mismo nivel, pero si en otros niveles diferentes. Un barco y un coche son diferentes entre sí, pero si “subimos” niveles de abstracción encontraremos coincidencias que nos harán ser capaces de ponerlos en el mismo grupo, como por ejemplo “medios de transporte o locomoción”. También podemos definir la abastracción entre niveles “parecidos”, por ejemplo un formula 1 es una especie de coche, pero tiene características diferentes a un coche, pero al ver un formula 1 podemos afirmar que es un tipo de coche, por las características en común que contiene a partir de un elemento base: el coche.
Diseño de clases para crear objetos Dentro de cualquier concepto de la realidad expuesto anteriormente, podemos diferenciar los objetos por “familias” a las que pertenecen. Dichas familias son conjuntos a los que pertenece cada objeto y que los diferencia de otras familias. Por ejemplo, los objetos son diferentes pero se pueden agrupar en un conjunto: los coches, barcos, bicicletas, motos o aviones son objetos diferenciados entre sí, pero que podemos incluir dentro de la familia de los “medios de transporte”. Lo mismo ocurriría con los mp3, las televisiones, los dvd o los aparatos de tdt, podemos incluirlos dentro de la familia de “aparatos electrónicos del hogar”, por ejemplo. Cuando estamos diseñando una aplicación, debemos decidir los objetos que vamos a utilizar en dicha aplicación según nuestra lógica. A partir de ese momento, cada objeto que vayamos a utilizar está en una “familia” que debemos utilizar para poder trabajar con el objeto. Es lo mismo que en un supermercado, si deseamos comprar fruta iremos a la sección de frutería y si deseamos comprar leche iremos a la sección de alimentación. A estas familias dónde se encuentran las clases para utilizar objetos se les llama paquetes. Cada paquete contiene un conjunto de clases que están relacionados con el tipo de paquete que vayamos a utilizar. Por ejemplo, si queremos trabajar con ficheros, debemos incluir en nuestra aplicación el paquete java.io, que es el paquete que contiene todas las clases para trabajar con ficheros. La ventaja de utilizar los paquetes depende del rendimiento y jerarquía de clases. Imaginad que vais al supermercado y encontrais todos los productos revueltos y no todo definido en cada sección. Habría que estar “buscando” dentro de todo el conjunto cada uno de los objetos que deseemos comprar. Por el contrario, si todo está ordenado por “secciones”, podremos ir perfectamente a las secciones que necesitamos sin necesidad de utilizar o recorrer las otras. Sucede lo mismo en la programación orientada a objetos de Java, cada clase está definida dentro de un paquete, y si queremos utilizar una funcionalidad específica (ficheros por ejemplo) bastaría con ir y utilizar esa sección, sin necesidad de utilizar otras secciones, llamadas paquetes. En el lenguaje de programación Java existen multitud de clases ya definidas y utilizables establecidas dentro de paquetes. Las bibliotecas estándar (llamadas paquetes) más utilizadas en Java son las siguientes:
java.lang: tipos de dato primitivos, números, strings, objetos, compilador, runtime, seguridad y threads (es el único paquete que se incluye automáticamente en todo programa Java al iniciar cualquier aplicación) java.io: clases que manejan entradas y salidas, utilizan lectura y escritura de ficheros. java.util: Estructuras genéricas, utilización de fechas, horas, determinados strings o colecciones. java.net: Clases para soportar redes: URL, TCP, UDP, IP, etc. java.awt: Clases para manejar la interface gráfica de Java en aplicaciones de escritorio, tales como ventanas, mensajes de alerta y objetos que tienen que ver con todo tipo de aplicaciones de escritorio. java.awt.image: Clases para el manejo de imágenes. java.swing: Es la evolución de clases gráficas awt, podemos definirlo como la siguiente versión gráfica de Java. Permite crear objetos para aplicaciones de escritorio con un diseño y características mejorados. www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
java.applet: Clases para la creación de applets y recursos para reproducción de audio.
Ver Video: Análisis de Aplicaciones , en la Unidad 2, en el Módulo 1, en la plataforma elearning
Actividades “Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades que encontrará en la unidad correspondiente de la plataforma eLearning”.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 3. Desarrollando y probando programas con tecnología JAVA Introducción Para poder realizar cualquier desarrollo sobre Java es necesario conocer todos los elementos que conforman la configuración. Para probar dichos ficheros de desarrollo, debemos configurar todo el kit JDK de Sun Microsystems y conocer todos los detalles para probar aplicaciones de Java. Se puede utilizar cualquier editor de texto para completar el desarrollo de Sun (Bloc de notas), también se pueden utilizar editores específicos de Java que permiten una cierta ayuda en el momento de desarrollar.
Objetivo
Aprender a instalar el software necesario para poder utilizar los programas de Java en desarrollo.
Conocer los diferentes ficheros de “acción” que Java nos ofrece, así cómo la configuración del entorno de desarrollo de trabajo.
Instalación y configuración del kit de desarrollo de Sun (JDK) Para poder desarrollar software con Java necesitamos una serie de herramientas que nos proporciona Sun a través de su JDK (Java Development Kit). •
Existen otras empresas, como IBM y Microsoft, que también tienen entornos de programación para Java. Salvo el de Microsoft, todos son compatibles al 100% con las especificaciones que estableció Sun para su lenguaje de programación.
Instalación del JDK de Sun. Lo primero será descargarnos la herramienta de desarrollo JDK (Java Development Kit) de la siguiente dirección: http://java.sun.com/ •
Tras la ejecución del programa de instalación, obtendremos en el directorio que hayamos especificado para tal fin, la siguiente estructura de directorios:
• A continuación, describimos los directorios y ficheros más importantes:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Directorios bin: En este directorio se encuentran todos los ficheros ejecutables del JDK. En su interior se encuentran los ficheros más importantes para el desarrollo de la tecnología Java. Los más importantes son: - javac.exe Es el compilador de Java, permite compilar los ficheros con extensión java y crear clases para el desarrollo. - java.exe Intérprete (JVM). Permite poder ejecutar los ficheros compilados (extensión class) y ejecutarlos. - javadoc.exe Generador de documentación para las clases y librerías de Java. - jdb.exe Depurador. Los programas de éste directorio los usaremos conforme los vayamos necesitando. demo: En este directorio hay una serie de ejemplos que Sun ha desarrollado con propósitos didácticos. En concreto encontraremos ejemplos sobre: - Applets. - JFC --> Java Foundation Classes. En la plataforma Java 2 (última versión de Java), Sun. docs: En este directorio está la documentación del API de Java. No viene por defecto con el JDK y hay que instalarlo por separado. lib: En este directorio se encuentran las clases de Java proporcionadas por Sun, y que conforman el API que utilizaremos en nuestros programas. las clases que nos interesan están comprimidas en un fichero que se llama: tools.jar jre: Java Run Environment. Entorno de Ejecución de Java proporciona las herramientas básicas para la ejecución de aplicaciones Java, sin incluir todas las herramientas que se proporcionan para su desarrollo (compilador, depurador, ...). b) Configuración del sistema. • El JDK no necesita ninguna configuración específica, sin embargo, si queremos que nuestras aplicaciones funcionen debemos configurar unas variables de entorno que dependerán del sistema operativo sobre el que estemos trabajando. Vamos a configurar las variables de entorno para el sistema operativo Windows: PATH: En esta variable debemos poner el camino hasta los ejecutable del JDK • El propósito de hacer esto es el poder ejecutar los ficheros ejecutables (javac, java…) desde cualquier directorio. CLASSPATH: Debe aparecer el camino hasta las clases que importemos en nuestros programas. En concreto debe aparecer el fichero tools.jar (toda la ruta al directorio). • El propósito es que el compilador (javac) encuentre las clases que importemos en nuestros programas. • No olvidar introducir también el propio directorio (.) de lo contrario tendremos errores. Vamos a mostrar como instalar y configurar las variables de entorno de Java para poder utilizar el kit de desarrollo de Java. Lo primero será instalarnos el kit de desarrollo de Java:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
A continuación, vamos a Mi PC y con el botón derecho, entramos en Propiedades.
Una vez dentro, entramos en Opciones Avanzadas y pulsamos sobre Variables de entorno:
Modificamos la variable de entorno PATH para poder ejecutar todos los comandos incluidos en el directorio BIN de java. (Compilador, Intérprete) Debemos incluir al final del todo la ruta dónde se ha instalado nuestra herramienta JDK y el directorio bin. Debemos separar cada elemento con punto y coma: ;C:\Archivos de Programa\Java\jdk1.5.0_22\bin
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Ahora debemos creamos una nueva variable llamada CLASSPATH. Ésta variable llamará a tools.jar ubicado en el directorio LIB. Este archivo es el comprimido que contiene todas las clases que utiliza java. Incluimos un punto para poder utilizar llamadas a las clases independientemente de la ubicación de nuestro proyecto.
.;C:\Archivos de Programa\Java\jdk1.5.0_22\lib\tools.jar
Procesos para crear un programa en Java Antes de explicar el proceso de creación de un programa, conviene explicar que en Java vamos a manejar tres tipos de aplicaciones: - Aplicación en modo texto: En este tipo de aplicaciones la interacción con el usuario (entrada de datos y presentación de resultados) se realiza en modo texto (no existirán cajas de texto, botones,...). El ratón no tendrá uso en estas aplicaciones. Son las aplicaciones que realizaremos en el primer bloque donde nuestro objetivo será aprender los conceptos básicos de Java. También es interesante cuando realizamos los prototipos de nuestros programas debido a que la depuración es más sencilla. - Aplicación en modo gráfico: En este tipo de aplicaciones la interacción con el usuario se realiza en modo gráfico. Estas aplicaciones pueden ser de todo tipo y no hay que pensar sólo en Internet: o Procesador de texto, bases de datos, entorno de programación, tratamiento de gráficos... - Miniaplicaciones (applets): Pequeños programas que no pueden ejecutarse de forma independiente sino que necesitan el soporte de un navegador. Estas programas están pensados para que sean invocados desde una página HTML, viajen a través de la red y se ejecuten el la máquina del cliente.
Proceso para crear una aplicación Java
Crear o o o
el código fuente: Para crear el código fuente de Java podemos utilizar: Un editor de texto plano como el Bloc de Notas. El editor de algún entorno de desarrollo. El fichero con el código fuente se guardará con extensión ".java"
Compilar el código fuente: La compilación del código fuente se realizará a través del compilador proporcionado por Sun en su JDK (Java Development Kit). El compilador se llama javac.exe y la sintaxis básica es: C:\javac.exe FicheroFuente.java
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
NOTA: El fichero llamado FicheroFuente.java debe llamarse igual que la clase y es imprescindible poner la extensión “.java” en el momento de escribir en la línea de comandos. Veremos el ejemplo práctico más adelante para entender el concepto de clase. La compilación se realiza desde una ventana de MS-DOS o desde el propio entorno que estemos usando, el cual nos ocultará la ejecución de javac. El proceso de compilación requiere que el sistema tenga configurada adecuadamente las variables de entorno para el correcto funcionamiento del comando anterior. Como resultado de la compilación obtenemos el fichero de bytecodes que tiene extensión ".class".
Ejecutar la aplicación: Para ejecutar el fichero de bytecodes es necesario pasarlo por el intérprete adecuado. El intérprete depende del tipo de programa java que hayamos implementado: o
Miniaplicaciones (applets) Es el navegador el intérprete y nosotros tenemos que preocuparnos tan sólo de incluir el applet en una página HTML.
o
Aplicación (texto o gráfica) Utilizaremos el intérprete proporcionado por el JDK de Sun que se llama java.exe. Su sintaxis es: C:\java.exe FicheroBytecodes.class
NOTA: Cuando llamamos al interpréte java.exe y al fichero “.class” no escribiremos el nombre de la extensión “class”, solamente debemos escribir el nombre del fichero compilado, pero manteniendo la diferencia entre mayúsculas y minúsculas.
Utilizando la ventana MS-DOS para compilar aplicaciones Java JAVAC es el compilador, debemos indicarle toda la ruta y el nombre del fichero con extensión “.java” que deseamos compilar. Diferenciación entre mayúsculas y minúsculas. JAVA es el intérprete de archivos con extensión class, debemos decirle toda la ruta y el nombre del archivo “.class” pero sin la extensión. Diferenciación de mayúsculas y minúsculas. NOTA: Para poder probar éste primer ejemplo debemos tener configuradas las variables de entorno que nos llevan al JDK de java y nos permiten compilar los ficheros. Todos los ficheros de Java son clases. Dentro de dichas clases escribiremos el código para crear nuestra “solución” a un problema que hayamos planteado. Para comenzar, utilizaremos un método llamado main que es el “arranque” de las clases no gráficas de Java. Simplemente esto quiere decir que toda “lógica” tiene un entorno y un lugar para probar dicho entorno, por ejemplo, si queremos hacer una página Web, el entorno para dicha clase web sería un navegador de Internet. Pues en nuestro caso, nuestro entorno será la ventana de Ms-Dos y para probar las aplicaciones necesitamos crearnos un método main para arrancar dicho entorno y generar nuestrá lógica en la clase. Como podemos comprobar, vamos a hacer un ejemplo sencillo para visualizar nuestra primera aplicación de Java y comprobar que tenemo todo listo para continuar.
Esqueleto de una clase CÓDIGO JAVA public class ClaseJava { public static void main(String args[]) { System.out.println("MI PRIMERA APLICACION"); } } www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Vamos a abrir un bloc de notas y escribiremos el código de nuestra primera clase. Debemos recordar que Java es un lenguaje de programación “Case Sensitive”, es decir, diferencia entre mayúsculas y minúsculas, por lo que escribiremos literalmente el contenido de nuestro primer ejemplo en el bloc de notas. A continuación vamos a guardar el fichero de nuestro bloc de notas con la extensión “.java” en la ubicación que vayamos a probar nuestros ejemplos. Es recomendable crearnos una carpeta para poder ubicar todas nuestras prácticas. Podemos utilizar cualquier otro editor de caracteres, pero es imprescindible que sólo almacene texto, no nos valdrían editores de texto del estilo Word o WordPad, ya que almacenan más información además del texto escrito, un ejemplo de estos editores puede ser UltraEdit o algún bloc de notas “free” que existen por internet y que tienen más características que el bloc de notas tradiciones de Windows. El nombre de nuestro fichero “java” debe tener el mismo nombre que nuestra clase, incluida la diferenciación de mayúsculas y minúsculas, en nuestro ejemplo debemos llamarlo ClaseJava.java. Voy a crear una carpeta en la unidad C:\ llamada PracticasJava y almacenaré las prácticas en dicha ubicación. En el bloc de notas seleccionaremos como Tipo: “Todos los archivos” y escribiremos la extensión “.java” para nuestra primera clase. NOTA: Podremos guardar las prácticas en cualquier ubicación, pero es conveniente guardarlas en alguna “ruta” fácilmente accesible ya que posteriormente tendremos que escribir dicha ruta en nuestra ventana de comandos de Ms-Dos.
A continuación abriremos una nueva ventana de comandos de Ms-dos. Para ello nos iremos al Inicio de Windows y pulsaremos sobre “Ejecutar” y escribiremos el comando cmd.exe. Esto depende del sistema operativo en el que estemos trabajando. Se nos abrirá una nueva ventana de comandos. Ahora debemos tener unas nociones básicas de Ms-Dos para trabaja y poder compilar nuestras clases de Java. Sobre la ventana de comandos escribimos: cd C:\PracticasJava Con el comando cd de Ms-Dos podremos entrar en cualquier directorio, según nuestra práctica yo he almacenado el fichero “java” de nuestra clase en dicha ubicación. Debemos posicionarnos en dicha ubicación. También podemos escribir “cd..” o “cd\” para ir a la raíz dónde hayamos almacenado los ficheros. Si queremos cambiar de unidad, bastaría con escribir la letra de la unidad seguida de dos puntos: “D:”. Con el comando “dir” veremos todos los ficheros que existen dentro de un directorio, aunque podemos complementar nuestras prácticas con las ventanas propias de Windows. Ya estamos posicionados sobre el lugar dónde tenemos almacenada la clase “.java”, ahora debemos utilizar el compilador javac.exe para poder compilar la clase. Escribiremos la llamada al compilador desde la ventana de comandos. www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
C:\PracticasJava>javac.exe ClaseJava.java Si no existen errores en la clase, no nos dará ningún mensaje y simplemente volverá a aparecer el símbolo de la unidad dónde estemos ubicados.
Ahora veremos que nos ha creado un fichero con extensión “.class”, que es el resultado de un fichero compilado con extensión “.java”, podemos verlo fácilmente si nos posicionamos en Windows dentro de nuestra carpeta de prácticas.
También podemos escribir el comando “dir” desde la ventana de comandos de Ms-Dos.
Es el momento de utilizar el intérprete de ficheros “.class”, nuestro intérprete es el comando java.exe. Para poder ejecutarlo debemos escribir desde la ruta dónde se encuentre la clase compilada la siguiente instrucción: java.exe ClaseJava Ahora ya podremos visualizar la lógica que tengamos dentro de la clase compilada:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Ver Video: Configuración entorno Java, en la Unidad 3, en el Módulo 1, en la plataforma elearning Actividades “Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades que encontrará en la unidad correspondiente de la plataforma eLearning”.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 4. Declarando, Inicializando y usando variables Introducción Dentro de cualquier lógica de negocio necesitamos almacenar información para poder realizar una aplicación. Dicha información se almacena en variables, que son espacios en la memoria y que permiten asignar y recuperar valores. Para trabajar con variables existen múltiples tipos de datos, dependiendo de lo que necesitemos realizar, pudiera ser que necesitemos realizar operaciones, por lo que almacenaríamos números, o pudiera ser que nuestro dato sea un nombre, por lo que almacenaríamos textos. Existen varios tipos de datos primitivos que aprenderemos a lo largo del módulo. Una variable también puede hacer referencia a un objeto, pudiendo acceder a todos los miembros que hayamos declarado en dicho objeto.
Objetivo
Conocer los tipos de datos primitivos de Java y su utilización en los programas.
Aprender la sintaxis de Java para la declaración y uso de variables en el código.
Elementos básicos del lenguaje y sintaxis de Java Comentarios en el programa Java tiene como todos los lenguajes de programación sus propias características para describir código, es decir sus propios comentarios y herramientas del lenguaje. Un elemento importante en el momento de crear una clase es comentar las acciones que estamos realizando. Dichos comentarios nos van a servir para dos propósitos, comprender las acciones que estamos realizando y documentar dichas acciones. Imaginemos que no trabajamos en un proyecto en un año y tenemos que retomarlo para implementar algunas características. Si no hemos puesto comentarios de las acciones que estamos realizando, la tarea de volver a revisar las acciones o de “saber” para que sirve cada acción puede llevarnos mucho tiempo. Otra de las ventajas de incluir comentarios se debe a que podemos encontrarnos con un código que otro programador ha realizado y no sabemos cómo ha hecho la funcionalidad de las acciones ni en que orden. Si el programador ha documentado su código, nos será mucho más sencillo adaptarnos a un código que no es nuestro para poder implementarlo. Para poner comentarios en nuestro código fuente java tenemos tres opciones: Una línea de comentario que empiece por // // Esto es un comentario System.out.println ("Hola mundo"); Varias líneas encerradas entre /* y */ /* Todo esto también es un comentario */ System.out.println ("Hola mundo"); www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Por último, podemos hacer varias líneas de comentario entre /** y */ /** Todo esto es un comentario de documentación */ public void miMedodo (int parametro) { CODIGO DEL MÉTODO } La diferencia entre el comentario que empieza por /** y el que empieza por /* es que el primero sale en la documentación generada por javadoc y en la mayoría de herramientas que hacen documentación a partir del código. El comentario que empieza por /* no sale en la documentación y es sólo para el programador. Hay unos detalles, sin embargo, que hay que tener en cuenta para comentarios que van a salir en la documentación. Conviene poner uno de estos comentarios delante de cada clase, cada método y cada atributo, de esta forma, en la documentación aparecerán convenientemente documentados las clases, métodos y atributos. El siguiente código nos sirve como ejemplo: package Mates; /** Clase con funciones matemáticas. Realiza operaciones trigonométricas, ecuaciones diferenciales e integrales */ public class ClaseMatematicas { /** Constante PI. Valor de PI=3.141618 */ public static final double PI = 3.1416; /** Devuelve el seno del ángulo que se le pasa como parámetro. El ángulo debe estar en radianes y es un double. */ public double senoAngulo(double angulo) { return 19.21; } } Una vez que tenemos la clase escrita, podemos utilizar la herramienta javadoc para crear la documentación con el comando: javadoc.exe ClaseMatematicas.java
Veremos que nos ha creado en el directorio dónde hemos creado la clase, una serie de páginas html y css que “copia” el formato de documentación de la API de Java.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Si pulsamos sobre el fichero ClaseMatematicas.html, veremos la documentación ya creada:
Es importante tener en cuenta que dentro de cada comentario, la primera frase -hasta el primer punto- saldrá como resumen de la clase, método o atributo. Conviene, por tanto, que esa frase tenga sentido por sí sola. Los comentarios de documentación, colocados inmediatamente antes de una declaración de variable o función, indican que ese comentario ha de ser colocado en la documentación que se genera automáticamente cuando se usa la herramienta javadoc.exe.
Identificadores Los identificadores nombran variables, funciones, clases y objetos, cualquier cosa que el programador necesite identificar. En la siguiente tabla se muestran las características de los identificadores: Primer caracter Siguientes caracteres Longitud Mayúsculas / Minúsculas No se pueden usar
Una letra, subrayado ( _ ) o el símbolo de dólar ($). Pueden ser letras, números o símbolos. No hay una longitud máxima establecida. Se distinguen las mayúsculas de las minúsculas. Palabras clave del lenguaje Java Palabras reservadas
En la siguiente tabla tenemos las palabras claves proporcionadas por la documentación de SUN. abstract double Int static Boolean else Interface super Break extends Long switch Byte final Native synchronized Case finally New this Catch float Null throw Char for Package throws Class goto * Private transient Const * if Protected try Continue implements Public void Default import Return volatile Do instanceof Short while
Separadores www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Normalmente definen la forma y función del código. En la siguiente tabla se especifican sus funciones.
Separador Paréntesis - ( )
Llaves - { } Corchetes - [ ] Punto y coma - ; Coma - , Punto - .
Función Para contener listas de parámetros en la definición y llamada a métodos. Definir precedencia en expresiones, contener expresiones para el control de flujo y realizar conversiones de tipo. Contener valores de matrices inicializadas automáticamente. Definir bloques de código para clases, métodos y ámbitos locales. Para declarar matrices y referenciar elementos de la matriz. Separar sentencias. Separa identificadores consecutivos en una declaración de variables, Para encadenar sentencias dentro de un bucle Para separar nombres de paquetes, subpaquetes y clases. Separar una variable o método de una variable de referencia.
Nombres de las clases, variables y métodos
Existe un convenio, no obligatorio, a la hora de nombrar las clases, las variables y métodos:
Clases Métodos Constantes Variables
Poner en mayúscula la primera letra de cada palabra con significado que forme el nombre de la clase. Mismo regla que en clases pero poniendo con minúscula la primera letra. En mayúsculas. En minúsculas.
Tipos de datos primitivos y variables
Java utiliza cinco tipos de elementos para abarcar todos los posibles datos que podemos necesitar en el desarrollo de una aplicación.
Enteros, reales en coma flotante, booleanos, caracteres y cadenas.
La siguiente tabla lista los tipos de datos primitivos soportados por Java, sus tamaños y su formato.
Tipo Byte Short Int Long Float Double Char Boolean
Tamaño/Formato 8-bit en complemento a 2 16-bit en complemento a 2 32-bit en complemento a 2 64-bit en complemento a 2 32-bit IEEE 754 64-bit IEEE 754 Caracter Unicode de 16 bits true o false
Descripción Entero con un byte de longitud. Entero corto (de 16 bits) Entero. Entero largo. Coma flotante de simple precisión. Coma flotante de doble precisión. Un único caracter. Un valor booleano (true or false).
Nombres de las variables
Al definir una variable se debe indicar su tipo y se deben respetar las siguientes normas con respecto al nombre que elijamos:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Norma Debe ser un identificador Java legal que contenga una serie de caracteres Unicode.
No debe ser una palabra clave ni reservada. Tampoco un valor booleano (true y false) No puede tener el mismo nombre que otra variable que se encuentre en el mismo ámbito.
Comentario Unicode es un sistema de codificación de caracteres diseñado para soportar texto escrito en varias lenguas. Permite la codificación de hasta 65536 caracteres de los cuales 34168 están siendo usados actualmente Ver la tabla presentada más arriba. Lo detectará el compilador. Ver el siguiente punto.
Vamos a ver un ejemplo práctico sobre declaración e inicialización de variables. Nos vamos a declarar una serie de variables e imprimiremos el resultado en una ventana de Ms-Dos. public class EjemploVariables { public static void main(String args[]) { byte b=-128; short s=32767; int i=-2147483648; long l=9223372036854775807L; System.out.println("El valor de b es: " + b); System.out.println("El valor de s es: " + s); System.out.println("El valor de i es: " + i); System.out.println("El valor de l es: " + l); } }
Podremos comprobar el resultado de asignar diferentes tipos de datos en variables:
Alcance de las variables El alcance de una variable viene acotado por la zona entre llaves { } en la cual se ha definido la variable. El siguiente dibujo lo representa:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Dependiendo dónde voy a declarar una variable, la variable tendrá una “visibilidad” u otra. Vamos a ver un ejemplo en el que declararemos una variable en la clase y otra en el método main: public class ClaseAmbitoVariables { int i = 25; public static void main(String args[]) { int i=19; System.out.println("El valor de i es " + i); } } Podemos comprobar que las dos variables pueden coexistir a pesar de que su nombre sea el mismo debido a que están declaradas en diferentes “secciones” o ámbitos de la clase.
Si declarásemos la misma variable dentro del mismo método main produciría una excepción indicándonos que la variable ya se ha declarado dentro del mismo método. public class ClaseAmbitoVariables { public static void main(String args[]) { int i = 25; int i=19; System.out.println("El valor de i es " + i); } }
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Declarando variables Al declarar una variable de un tipo e inicializarla con un valor, el compilador normalmente sabe de qué tipo se trata. Sin embargo, hay ocasiones en la que el tipo es ambiguo y hay que guiar al compilador proporcionándole información adicional. Estos casos se reflejan en la siguiente tabla: Caso Para inicializar una variable con un dato en hexadecimal se debe poner 0x... Para inicializar una variable con un dato en octal se pone un 0 delante. Se puede colocar una letra (mayúscula o minúscula) al final del valor para indicar su tipo. L para long, F para float y D para Double. La exponenciación se indica con la letra e, tomando como referente la base 10. El compilador normalmente codifica estos números como double aunque se definan como float. No existe representación para número binarios
Ejemplo char c= 0xffff; byte b= 0x7A; int i= 0177; float f= 1F; long l= 100L; double d= 1d; float f= 1e-45f; Hay que verlo como 1.3 x 10-45
Antes de usar una variable en Java, debemos declararla, especificando su tipo. A continuación se indica cómo se declaran las variables en Java:
tipodato nombre = valor; Ahora, podemos ver cómo se declara una variable de tipo int, es decir, contiene un entero: public class PrimeraClase ( public static void main(String[] args) { int dias = 31; System.out.println(“Numero de dias: “+ dias); } }
Declaración de variables de tipo entero Java utiliza cuatro tipos de datos para almacenar enteros, cada uno con su propio número de bytes alojados en memoria: byte (un byte), short (dos bytes), int (cuatro bytes) y long (ocho bytes). Utilizar un tipo de dato entero u otro depende de los valores de datos que deseamos almacenar, así como de otras consideraciones, como cuánta memoria hay disponible. www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Vamos a mostrar un ejemplo práctico en el que utilizamos todos los tipos de datos enteros y posteriormente mostramos su valor por pantalla: public class PruebaVariables { public static void main(String[] args) { byte byte1; short short1; int int1; long long1; byte1 = 1; short1 = 100; int1 = 10000; long1 = 100000000; System.out.println("Valor de byte1 = System.out.println("Valor de short1 = System.out.println ("Valor de int1 = " System.out.println("Valor de long1 = } }
" + byte1); " + short1); + int1) ; " + long1);
Y el resultado de la aplicación:
Declaración de variables de coma flotante Java incluye dos tipos de variables en coma flotante, cada uno con su propio número de bytes para aljcar en memoria. Los dos tipos que tenemos son float (cuatro bytes) y double (ocho bytes). Vamos a visualizar un ejemplo en el que vamos a declararnos los tipos de datos float y double para mostrarlos por pantalla. public class PruebaVariables { public static void main(String[] args) { float float1; double double1; float1 = 21.1231157111; double1 = 19.11437687311E+9; System.out.println("Valor de float1 = " + float1); www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
System.out.println("Valor de double1 = " + double1); } }
Resultado de la compilación:
Podremos comprobar que en la compilación nos aparece una excepción que indica que podemos perder precisión en los datos. Esto sucede porque en Java todos los tipos de datos con decimales son double. Si queremos especificar un tipo de dato float, debemos hacerlo con F al final del número a asignar. public class PruebaVariables { public static void main(String[] args) { float float1; double double1; float1 = 21.1231157111F; double1 = 19.11437687311E+9D; System.out.println("Valor de float1 = " + float1); System.out.println("Valor de double1 = " + double1); } }
Resultado de la aplicación ya compilada:
Declaración de variables de tipo carácter char Se pueden declarar variables de tipo carácter con la palabra reservada char. Los posibles valores que se pueden almacenar en una variable char son caracteres Unicode del 0 al 65535, pero el código ASCII sólo tiene caracteres dentro del rango de 0 a 255. Para asignar un dato carácter a un char, se realiza mediante el símbolo de la comilla simple. Vamos a comprobar una aplicación en la que asignaremos valores de tipo carácter e int a un tipo de datos char. Comprobaremos que el resultado es la “traducción” del código ASCII a una representación de letra en la aplicación. public class PruebaVariables { public static void main(String[] args) www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
{ char char1, char2; char1 = 88; char2 = 'B'; System.out.println("Valor de char1 (Entero ASCII) = " + char1); System.out.println("Valor de char2 (Letra) = " + char2); } } Y vemos que como resultado de la compilación muestra el carácter X como resultado del valor del código ASCII 88.
Declaración de variables de tipo boolean Las variables de tipo verdadero o falso se declaran con la palabra clave boolean. En Java, las variables de tipo booleano sólo pueden tener dos valores: verdadero o falso, no pudiendo guardar valores numéricos como 0 o 1 como sucede en otros lenguajes de programación. Dichas variables se utilizan para almacenar información y poder realizar un análisis de nuestro código dependiendo del resultado de verdadero o falso. Se utilizan para realizar bifurcaciones en nuestro código, de forma que el código no sea lineal, sino que entre por alguna de las bifurcaciones. Los valores de true o false en la asignación a éstas variables deben ir en minúscula. Vamos a visualizar un ejemplo en el que asignaremos valores a dos variables de tipo boolean: public class PruebaVariables { public static void main(String[] args) { boolean boolean1, boolean2; boolean1 = true; boolean2 = false; System.out.println("Valor de boolean1 = " + boolean1); System.out.println("Valor de boolean2 = " + boolean2); } }
Y el resultado de la compilación es:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Conversión entre tipos (casting) Java permite convertir un variable de un tipo de dato a otro. A esta conversión se le conoce como
"casting". Se permite la conversión de un tipo primitivo a cualquier otro tipo primitivo, excepto en el caso de los booleanos. Para forzar la conversión de un tipo a otro se utiliza la siguiente sintaxis:
variable_tipo_A= (tipo_A) variable_tipo_B; Dependiendo del tipo de dato, podremos utilizar varios tipos de conversión, con métodos estáticos desde la clase o con casting. Java es un lenguaje muy robusto en cuanto a los tipos, y como consecuencia de ello, con frecuencia nos enfrentamos a la situación de asignar una variable de un tipo a una variable de otro. Para realizar dicha acción se realiza lo que se denomina casting. Existen dos formas de hacerlo: contando con una conversión automática y haciendo explícitamente un cast de tipos.
Conversión automática de tipos de dato Cuando asigna un tipo de dato a una variable de otro tipo, Java convertirá el dato al nuevo tipo de variable de forma automática si se cumplen las siguientes condiciones:
Los tipos del dato y de la variable son compatibles.
El tipo de destino tiene un rango mayor que el de origen.
Poniendo un ejemplo, se puede asignar un valor de tipo byte a una variable int, ya que byte e int son tipos compatibles y las variables int tienen un rango mayor que los valores byte. Por lo tanto, no se perderá ningún dato en la conversión de tipos. Esto es un ejemplo: public class PruebaVariables { public static void main(String[] args) { byte byte1 = 19; int int1; int1 = byte1; System.out.println("Valor de int1 = " + int1); System.out.println("Valor de byte1 = " + int1); } } Y el resultado de la compilación es:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
El compilador de Java hace la conversión de tipos automáticamente. Este tipo de conversiones, en las que se convierte a un tipo de datos que tiene mayor rango, se llaman extensión de conversiones. En ellas, los tipos numéricos, como entero o coma flotante, son compatibles entre sí. En cambio, los tipos char y boolean no son compatibles entre sí y tampoco con los tipos numéricos.
Casting entre tipos de datos Si se está asignando un valor que es de un tipo con un rango mayor que la variable a la que se le está asignando, se está ejecutando lo que se denomina estrechamiento de conversiones. El compilador de Java no las ejecuta automáticamente, debido a que perderiamos la precisión en la asignación del valor de las variables.. Si deseamos hacer un estrechamiento de conversiones, debemos usar explícitamente un casting, que tiene la siguiente sintaxis: Variable Destino = (Tipo de dato destino) valor a asignar; Vamos a hacer un ejemplo en el que intentaremos convertir un tipo de dato int a un tipo de datos byte, por lo que tiene menos precisión y debería de darnos una excepción en la compilación. public class PruebaVariables { public static void main(String[] args) { byte byte1; int int1 = 21; byte1 = int1; System.out.println("Valor de conversion de byte1 = " + byte1); } }
Como podemos comprobar, existe una pérdida de precisión, ya que los dos tipos de datos son compatibles entre sí, pero un valor de tipo int es superior a un tipo de datos byte, por lo que la conversión no se realiza de forma automática y tenemos que utilizar un casting: www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
public class PruebaVariables { public static void main(String[] args) { byte byte1; int int1 = 21; byte1 = (byte) int1; System.out.println("Valor de conversion de byte1 = " + byte1); } } El resultado ya es satisfactorio:
Como podemos comprobar ahora, el resultado de la compilación es diferente y ya nos permite visualizar los datos, otro tipo de problema sería que almacenásemos un número mayor del que permite byte, por lo que nos daría una excepción, pero en tiempo de ejecución: public class PruebaVariables { public static void main(String[] args) { byte byte1; int int1 = 222222; byte1 = (byte) int1; System.out.println("Valor de conversion de byte1 = " + byte1); } } Como podemos visualizar, nos permite la conversión, pero perdemos el valor de la variable al perder la precisión entre tipos de datos.
Strings (Cadenas) Un string o cadena es una secuencia de caracteres almacenados en memoria y accesibles como una unidad. www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Aunque existen diversas formas que veremos más adelante, aquí definiremos e inicializaremos los strings de la siguiente manera: String mensaje="Hola Mundo"; Es muy importante manejar esta clase de datos debido a que los entornos gráficos recogen y presentan los datos en este formato.
Ver Video: Tipos de Casting, en la Unidad 4, en el Módulo 1, en la plataforma elearning Laboratorio: Casting entre tipos de datos. Objetivos Comprender el funcionamiento del concepto de casting, asi como los métodos estaticos de las clases para conversión entre tipos de datos y objetos.
Enunciado Realizaremos una aplicación en la que mostraremos los diferentes tipos de conversión posibles entre objetos, de forma automática o utilizando los métodos static de las clases, tales como String.valueOf o Integer.parseInt. Podremos modificar el ejemplo y visualizar que sucedería en el caso de convertir un conjunto de caracteres “doublé” a un int. O por ejemplo añadir un char e intentar convertirlo a int, y a la inversa.
Solución: CÓDIGO JAVA public class CastingObjetos { public static void main(String[] args) { System.out.println("Casting entre objetos"); String texto; int numero = 25; double decimal = 19.21; byte bit = (byte)255; float f = 65.55F; boolean valor = true; texto = "22"; numero = Integer.parseInt(texto); www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
System.out.println("Convertido String a int: " + numero); numero = 4567; texto = String.valueOf(numero); System.out.println("Convertido int a String: " + texto); numero = (int) decimal; System.out.println("Convertido double a int: " + numero); System.out.println("Perdida de precision de double: " + decimal); texto = String.valueOf(decimal); System.out.println("Convertido double a String: " + decimal); decimal = f; System.out.println("conversion automatica float a double: " + decimal); f = (float)decimal; System.out.println("Convertido double a float: " + f); System.out.println("Perdida de precision de float: " + decimal); texto = String.valueOf(f); System.out.println("Convertido float a String: " + texto); texto = String.valueOf(valor); System.out.println("Convertido boolean a String: " + texto); System.out.println("-----------------------------------------"); System.out.println("Fin de programa"); }
}
Actividades “Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades que encontrará en la unidad correspondiente de la plataforma eLearning”.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 5. Creando y usando Objetos Introducción Como hemos ido aprendiendo a lo largo del módulo, podemos declararnos variables para almacenar valores simples (números, letras, decimales). Pero el problema lo podemos encontrar si deseamos almacenar algo más complejo, por ejemplo, los datos de una factura o los datos de un determinado registro de compra. Dentro de dicho supuesto, una factura está compuesta por múltiples valores simples que conforman un conjunto, el precio, el iva, el descuento, el destinatario… Gracias a la tecnología de Java, podemos declararnos objetos, llamados Clases, que nos permiten almacenar gran cantidad de objetos simples desde un mismo lugar, o lo que es lo mismo, nos permite definir un objeto compuesto para manejar y utilizar sus objetos simples. A lo largo del módulo vamos a aprender a crearnos objetos propios y a manejar un objeto ya creado como es la clase String, con sus métodos y miembros de objeto.
Objetivo
Conocer la diferencia entre los tipos de datos primitivos de Java y la creación de un objeto y uso de sus clases.
Utilización de la clase String dentro del lenguaje de Java.
Declarar, instanciar e inicializar variables de referencia de objeto Una clase es una agrupación de datos (miembros o campos) y de funciones (métodos) que operan sobre esos datos. La definición de una clase se hace de la siguiente forma: public class NombreClase { // definición de variables y métodos } La palabra public es opcional, si no se pone, la clase tiene la visibilidad por defecto, esto significa que sólo es visible para las demás clases del package. Todos los métodos y variables deben ser definidos dentro de las llaves bloque {...} de la clase. Un objeto es un elemento concreto para usar de una clase. Las clases son la definición de los elementos de un objeto, mientras que los objetos son variables concretas de un tipo determinado de una clase. NombreClase MiObjeto; Vamos a enumer algunas características importantes de las clases:
Todas las variables y funciones de Java deben pertenecer a una clase. No hay variables y funciones globales para todo el entorno. Si una clase deriva de otra, hereda todas sus variables y métodos. Java tiene una jerarquía de clases estándar de la que pueden derivar las clases que crean los usuarios.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Una clase sólo puede heredar de una única clase (en Java no existe herencia múltiple). Si al declarar una clase no se especifica de qué clase deriva, por defecto dicha clase hereda de Object. La clase Object es la base de toda la jerarquía de clases de Java. En un fichero se pueden definir varias clases, pero en un fichero no puede existir más que una clase public. Dicho fichero se debe nombrar como la clase public que contiene con extensión *.java. Con algunas excepciones, lo normal es escribir una sola clase por fichero. Si una clase incluida en un fichero no contiene el ámbito public, no es imprescindible que el fichero se nombre como la clase. Los métodos de una clase pueden referirse de modo global al objeto de esa clase al que se aplican por medio de la palabra clave this. Dicha palabra clave hace referencia al objeto sobre el que se está creando la clase. Las clases se pueden unir en packages, incluyendo una sentencia al principio del fichero (package NombrePaquete;). Esta unión en packages está relacionada con la jerarquía de directorios y ficheros en la que se almacenan las clases.
Todos estos conceptos nos llevan a la creación de objetos de referencia, dichos objetos de referencia son clases creadas con unos métodos y características concretas. Para crearnos objetos de referencia no se realiza sobre la propia clase Factura, digamos que la clase Factura es una definición de clase y para su utilización se realiza sobre cualquier otra clase de Java. Para visualizar un objeto de referencia vamos a mostrar un ejemplo y su utilización. Nos vamos a crear una nueva clase llamada Factura. Una factura está compuesta por un nombre de titular, un concepto, un precio, el iva y el total de la factura. public class Factura { public String NombreTitular; public String ConceptoFactura; public double Precio; public double Total; public double Iva; } Acabamos de crearnos una clase en la que podemos almacenar una serie de datos primitivos en su conjunto. Dicha clase contiene una serie de miembros que almacenará cada objeto creado de ese tipo concreto de clase. Cada objeto Factura, es decir cada instancia de la clase, tiene su propia copia de las variables miembro. Las variables miembro de una clase (también llamadas campos) pueden ser de tipos primitivos (boolean, int, long, double) o referencias a objetos de otra clase (composición). En nuestro ejemplo, hemos creado cinco variables miembro de la clase factura, dichas variables miembro son elementos que pertenecen a la clase Factura y sólo pueden ser utilizadas por objetos de la clase Factura. Cada Factura que creemos tendrá unos valores diferentes para cada miembro. public class UtilizacionFactura { public static void main(String[] args) { Factura f1 = new Factura(); f1.NombreTitular = "Adrian Ramos"; f1.ConceptoFactura = "IPad"; f1.Precio = 540; f1.Iva = 30; f1.Total = 570; System.out.println("Datos de la factura numero 1"); System.out.println("Nombre Titular: " + f1.NombreTitular); www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
System.out.println("Concepto Factura: " + f1.ConceptoFactura); System.out.println("Precio: " + f1.Precio); System.out.println("Iva: " + f1.Iva); System.out.println("Total: " + f1.Total); System.out.println("-------------------------------------"); Factura f2 = new Factura(); f2.NombreTitular = "Lucia Serrano"; f2.ConceptoFactura = "PSP"; f2.Precio = 169; f2.Iva = 15; f2.Total = 184; System.out.println("Datos de la factura numero 2"); System.out.println("Nombre Titular: " + f2.NombreTitular); System.out.println("Concepto Factura: " + f2.ConceptoFactura); System.out.println("Precio: " + f2.Precio); System.out.println("Iva: " + f2.Iva); System.out.println("Total: " + f2.Total); } } Como podemos comprobar, cada objeto referenciado de la clase factura contiene unos datos diferentes para cada elemento. Es decir, cada miembro de la instancia de Factura almacena unos datos diferentes en cada objeto.
Un aspecto muy importante del correcto funcionamiento de los programas es que no haya datos sin inicializar. Por eso las variables miembro se inicializan siempre de modo automático, incluso antes de llamar al constructor. Sin embargo, lo más adecuado es inicializar las variables miembro dentro del constructor. Un contructor, como veremos más adelante, es un método de inicio de la clase. Cuando llamamos a la palabra clave new al crear la instancia, estamos llamando al constructor de la clase sobre la que estamos instanciando un objeto. Un constructor se define con el mismo nombre de la clase y es el primer lugar que el código lee en una clase. Vamos a comprobarlo modificando el ejemplo Factura: Para hacer referencia a los objetos que pertenecen a la clase sobre la que estamos escribiendo se utiliza la palabra clave this. Dicha palabra hace referencia a todos los cualquier elemento declarado en la clase. public class Factura www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
{ public String NombreTitular; public String ConceptoFactura; public double Precio; public double Total; public double Iva; //CONSTRUCTOR DE FACTURA public Factura() { //VAMOS A INICIALIZAR LOS MIEMBROS DE LA CLASE this.NombreTitular = "sin titular"; this.ConceptoFactura = "sin concepto"; this.Precio = 0.0; this.Iva = 0.0; this.Total = 0.0; } } Si ahora utilizamos un objeto de la clase Factura, solamente instanciando un objeto, los valores iniciales se han creado desde el constructor. public class UtilizacionFactura { public static void main(String[] args) { Factura f1 = new Factura(); System.out.println("Datos de la factura CONSTRUIDA"); System.out.println("Nombre Titular: " + f1.NombreTitular); System.out.println("Concepto Factura: " + f1.ConceptoFactura); System.out.println("Precio: " + f1.Precio); System.out.println("Iva: " + f1.Iva); System.out.println("Total: " + f1.Total); } } Como resultado vemos los valores iniciales creados desde el constructor:
Variables static de clase Una clase puede tener variables propias de la clase y no de cada objeto. A estas variables se les llama variables de clase o variables static. Las variables static se suelen utilizar para definir constantes comunes para todos los objetos de la clase o variables que sólo tienen sentido para toda la clase. Las variables de clase se crean anteponiendo la palabra static a su declaración. Para llamarlas se utiliza el nombre de la clase. www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
public static int VariableEstatica; Las variables static se llaman desde la clase y no pueden hacer referencia al objeto, es decir, no pueden utilizar la palabra this, debido a que todas las instancias de la clase tendrán el mismo valor. Como ejemplo, podemos visualizarlo fácilmente incluyendo una variable static dentro de nuestro ejemplo de factura: public class Factura { public static String TipoIva = "Iva del 16%"; public String NombreTitular; … } Ahora vamos a utilizar la clase Factura: public class UtilizacionFactura { public static void main(String[] args) { Factura f1 = new Factura(); Factura f2 = new Factura(); f1.NombreTitular = "Adrian Ramos"; f2.NombreTitular = "Lucia Serrano"; System.out.println("Nombre Titular Factura 1: " + f1.NombreTitular); System.out.println("Nombre Titular Factura 2: " + f2.NombreTitular); System.out.println("Tipo Iva: " + Factura.TipoIva); Factura.TipoIva = "Iva 18%"; System.out.println("Tipo Iva: " + Factura.TipoIva); } } Como podemos comprobar, las variables miembro tienen un valor diferente para cada instancia del objeto, mientras que la variable static TipoIva no hace referencia a ninguno de los dos objetos (f1 y f2), sino que hace referencia directamente sobre la clase, lo que quiere decir que todos los objetos de la clase Factura tendrán el mismo valor. Si modificamos el contenido de la variable static, se modifica para toda la clase.
Las variables miembro static se crean en el momento en que pueden ser necesarias: cuando se va a crear el primer objeto de la clase, en cuanto se llama a un método static o en cuanto se utiliza una variable static de dicha clase. Lo importante es que las variables miembro static se inicializan siempre antes que cualquier objeto de la clase.
Variables final o constantes Una variable de un tipo primitivo declarada como final no puede cambiar su valor a lo largo de la ejecución del programa, es una constante. www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Java permite separar la definición de la inicialización de una variable final. La inicialización puede hacerse más tarde, en tiempo de ejecución, llamando a métodos o en función de otros datos. La variable final definida es constant, pero no tiene por qué tener el mismo valor en todas las ejecuciones del programa, pues depende de cómo haya sido inicializada. Además de las variables miembro, también las variables locales y los propios argumentos de un método pueden ser declarados como final. Para declarar una variable constante, bastaría con incluir la palabra final en la declaración de la variable: public final int NombreConstante; Vamos a mostrar un ejemplo: public class Factura { public static String TipoIva = "Iva del 16%"; public final double PI; public String NombreTitular; public String ConceptoFactura; public double Precio; public double Total; public double Iva; //CONSTRUCTOR DE FACTURA public Factura() { //VAMOS A INICIALIZAR LOS MIEMBROS DE LA CLASE this.PI = 3.1416; this.NombreTitular = "sin titular"; this.ConceptoFactura = "sin concepto"; this.Precio = 0.0; this.Iva = 0.0; this.Total = 0.0; } } Como podemos comprobar, hemos declarado una variable final y la hemos inicializado en el constructor, lo que no podemos hacer es cambiar su valor posteriormente, ni en el uso de un objeto Factura, ni en la propia clase factura. public class UtilizacionFactura { public static void main(String[] args) { Factura f1 = new Factura(); System.out.println("Valor de la constante PI: " + f1.PI); } }
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
La clase String Un String es una variable referenciada asociada a un objeto de la clase java.lang.String. Se emplea para almacenar conjuntos de caracteres. Las Strings tienen una característica que las diferencia del resto de objetos: son inmutables, es decir, cuando se intenta modificarlas, por ejemplo al aplicarles un método, no se modifican sino que se crea otra instancia con un objeto de la clase String nuevo. Dicho concepto se llama inmutabilidad. Para comprender mejor dicho concepto vamos a crear un ejemplo práctico: public class EjemploString { public static void main(String args[]) { String texto = "Clase String"; System.out.println(texto); texto += " Java"; System.out.println(texto); } } Inicialmente, la variable texto se crea con el valor Clase String. Cuando se ejecuta la instrucción texto += “Java”, se crea un nuevo objeto de la clase String cuyo contenido es Clase String Java y se destruye el antiguo objeto. Estamos creando dos instancias de objeto sobre la misma variable.
Podremos observar que siendo una String una variable referenciada no se emplea constructor para crearla sino que se siguen las mismas pautas que en las variables primitivas. Cuando veamos los constructores de String se explicará el motivo. Dentro de un objeto de la clase String, el lenguaje Java crea un array de caracteres. A este array se accede a través de las funciones o métodos miembros de la clase. Los strings u objetos de la clase String se pueden crear explícitamente o implícitamente. Para crear un string implícitamente bastaría poner una cadena de caracteres entre comillas dobles. Por ejemplo, cuando escribimos la instrucción: System.out.println("Primer programa Java"); Java crea un objeto de la clase String automáticamente de forma implicita. Para crear un string explícitamente debemos acceder al constructor de la clase, como por ejemplo: String texto=new String("Primer programa Java"); También se puede escribir, alternativamente String texto ="Primer programa Java"; Para crear un string nulo se puede hacer de varias formas: String texto =""; www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
String texto =new String(); Un string nulo es aquél que no contiene caracteres, pero es un objeto de la clase String sin contenido, pero creado o instanciado. Sin embargo, si escribimos ésta instrucción: String texto; Estamos declarando un objeto texto de la clase String, pero aún no se ha creado ningún objeto de esta clase. La clase String incluye métodos para examinar caracteres individuales de la secuencia, para comparar diferentes cadenas, para encontrar textos en una cadena, para extraer subcadenas o para convertir textos en mayúsculas o minúsculas por ejemplo. El símbolo para concatenar cadenas es el símbolo +. También puede servir para convertir otro tipo de objetos a string y unirlos en un nuevo objeto de la clase. La conversión de objetos a la clase String se realiza mediante el método toString(), definido en todas las clases Java. El paquete dónde se encuentra la clase String es java.lang.String.
Constructores de la clase String Constructor Summary -
-
-
-
-
String() Crea una nueva instancia del objeto String que representa una cadena de caracteres vacía. String(byte[] bytes) Construye un nuevo String decodificando los bytes del array en un conjunto de caracteres. String(byte[] bytes, int offset, int length) Construye un nuevo objeto de la clase String decodificando el array de bytes en un conjunto de caracteres, indicando el inicio del array de bytes y la longitude de caracteres que deseamos construir. String(char[] value) Construye un nuevo objeto String con la secuencia de caracteres que hay incluidos dentro del array de caracteres. String(char[] value, int offset, int count) Construye un nuevo objeto String con la secuencia de caracteres que hay incluidos dentro del array de caracteres, indicando el inicio del array y la longitud de caracteres que deseamos incluir en el nuevo objeto String. String(String original) Construye un nuevo objeto String, a partir de otro objeto String indicado en constructor como parámetro. String(StringBuffer buffer) Construye un nuevo objeto String, a partir de un objeto StringBuffer indicado en constructor como parámetro.
Métodos de la clase String Cada método de la clase String realiza una acción sobre el objeto. Dependiendo del método que vayamos a utilizar, podemos realizar acciones como convertir a mayúsculas el String o recuperar un carácter dentro de la cadena de caracteres. Debemos de tener en cuenta que todas las cadenas de caracteres en Java comienzan en la posición cero y que nunca podremos sobrepasar la longitud de un texto. -
charAt(int index) www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
-
-
-
-
-
-
-
-
-
-
-
-
-
Devuelve un char, el character ubicado dentro de la cadena en la posición que indiquemos como número. compareTo(Object o) Compara un objeto String con otro objeto, devolviendo un int. Devuelve cero en el caso que sean diferentes y uno en el caso de que coincidan. compareTo(String anotherString) Compara un objeto String con otro objeto String lexicográficamente, devolviendo un int. Devuelve cero en el caso que sean diferentes y uno en el caso de que coincidan. compareToIgnoreCase(String str) Compara un objeto String con otro objeto String lexicográficamente sin tener en cuente las diferencias entre mayúsculas y minúsculas del texto. Devuelve un int. Devuelve cero en el caso que sean diferentes y uno en el caso de que coincidan. concat(String str) Concatena el objeto String enviado como parámetro al final del String sobre el que se realize la acción. Devuelve un String con el conjunto como resultado. contentEquals(StringBuffer sb) Devuelve verdadero solo si el String representa la misma secuencia de caracteres que el objeto StringBuffer enviado como parámetro. copyValueOf(char[] data) Método static que devuelve un String que representa el conjunto de caracteres enviado como parámetro en el array de char. copyValueOf(char[] data, int offset, int count) Método static que devuelve un String que representa el conjunto de caracteres enviado como parámetro en el array de char, indicando el inicio de caracteres en el array y la longitud de caracteres que deseamos recuperar. endsWith(String suffix) Devuelve verdadero o falso si la cadena finalize con el texto enviado como parámetro. equals(Object anObject) Compara si un String es igual a un object. equalsIgnoreCase(String anotherString) Compara un String con otro String sin tener en cuenta la diferencia entre mayúsculas y minúsculas. getBytes() Método que devuelve un array de bytes a partir de la secuencia de caracteres contenida en el objeto String. getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) Método que copia los caracteres del String dentro del array de caracteres que se envía como parámetro. Debemos indicar la posición de inicio y final del String y la posición desde la que deseamos copiar dentro del array de char. hashCode() Devuelve el código hash del String. indexOf(String str) Método que busca un texto dentro de la cadena y devuelve la posición en la que se encuentra. Busca la primera ocurrencia dentro del texto. Si no encuentra la cadena especificada devuelve 1. indexOf(String str, int fromIndex) Método que busca un texto dentro de la cadena y devuelve la posición en la que se encuentra, indicando la posición inicial a buscar. Busca la primera ocurrencia dentro del texto. Si no encuentra la cadena especificada devuelve -1. lastIndexOf(String str) www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
-
-
-
-
-
-
-
-
-
Método que busca un texto dentro de la cadena y devuelve la posición en la que se encuentra. Busca la primera ocurrencia dentro del texto empezando desde el final. Si no encuentra la cadena especificada devuelve -1. lastIndexOf(String str, int fromIndex) Método que busca un texto dentro de la cadena y devuelve la posición en la que se encuentra, indicando la posición inicial a buscar. Busca la primera ocurrencia dentro del texto empezando desde el final. Si no encuentra la cadena especificada devuelve -1. length() Devuelve el número de caracteres que hay en la cadena. replace(char oldChar, char newChar) Método que devuelve un String como resultado de reemplazar todos los caracteres que existan en la cadena por otro character indicado como parámetro en la cabecera del método. split(String regex) Devuelve un array de la clase String utilizando como separador los caracteres contenidos dentro de la expresión enviada como parámetro. startsWith(String prefix) Método que devuelve verdadero o falso indicando si la cadena comienza por el texto enviado como parámetro. startsWith(String prefix, int toffset) Método que devuelve verdadero o falso indicando si la cadena comienza por el texto enviado como parámetro, indicando la posición desde la que se va a comenzar a buscar. substring(int beginIndex) Método que devuelve una subcadena desde la posición que indiquemos como inicio hasta el final del texto. substring(int beginIndex, int endIndex) Método que devuelve una subcadena desde la posición que indiquemos como inicio hasta la posición indicada como final. toCharArray() Método que convierte el String en un array de char. toLowerCase() Método que convierte los caracteres del String a minuscula. toUpperCase() Método que convierte los caracteres del String a mayúscula. trim() Método que devuelve un String eliminando los espacios del texto tanto por la izquierda como por la derecha. valueOf(int i) Devuelve un string que es la representación del tipo de dato enviado como argumento a una cadena de caracteres. Éste método es estático. Hay métodos equivalentes donde el argumento es un float, double, etc.
Introducción a los flujos o streams Los flujos surgen por la necesidad de las aplicaciones Java de interaccionar con el exterior de dos posibles formas: Generando salida a la consola del DOS, a un fichero, etc. Capturando datos procedentes del teclado, de ficheros, de páginas web, etc. Concepto de flujo: es como un río. El agua en movimiento es el flujo, su contenido son los datos. Lo que permite que esos datos viajen de un origen a un destino es el agua en movimiento, es decir, el www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
flujo. En el caso de la captura desde un programa Java, de datos introducidos por un usuario mediante teclado, el origen es el teclado, el destino, el programa Java y los datos, lo tecleado por el usuario. Java modela flujos mediante clases del paquete java.io. Este paquete se estudiará más adelante en el curso, por el momento se va a explicar cómo una aplicación Java captura datos introducidos por el usuario a través del teclado y cómo realiza todo tipo de operaciones sobre los mismos.
Capturar datos desde teclado Necesitamos los siguientes elementos en nuestra aplicación: Obtener un objeto que modele la fuente de entrada de datos "teclado" en un programa Java. Más adelante se estudiarán otras fuentes de entrada de datos como ficheros o conexiones a sockets. Para ello, lo primero que debe tenerse presente es que el teclado es la entrada estándar de datos en un PC. A continuación, debe tenerse en cuenta, que cualquier entrada genérica de datos a un programa Java, se modela mediante un objeto de la clase abstracta java.io.InputStream. Bueno, pues en la API se observa que un objeto de esta clase es lo que devuelve la variable de campo estática "in" de la clase java.lang.System. Además, la explicación API de esta variable nos dice que representa la entrada estándar de datos de un programa Java. En los códigos que capturen datos procedentes del teclado, se empleará System.in para modelar el teclado. La salida estándar de datos en un PC es la consola del DOS. La salida genérica de datos de un programa Java se modela mediante un objeto de la clase abstracta java.io.OutputStream. En la API, se observa que un objeto PrintStream (hereda de OutputStream y, por tanto, es un objeto OutputStream) es lo que devuelve la variable de campo estática "out" de System. Además, la explicación API de esta variable dice que representa la salida estándar de datos de un programa Java. En los códigos que generen salida a través de la consola del DOS, se empleará System.out para modelar la consola del DOS. Gracias a ésta teoría, podemos responder a la pregunta: ¿Cómo se escribe en la consola? Escribimos en la consola a través de métodos adecuados de PrintStream. Concretamente se han empleado print(..) y println(..) para mostrar datos de salida en cualquier aplicación que hemos estado probando. No es esta la única forma de interaccionar con el exterior que tiene un código Java. Más adelante se verá cómo se puede generar salida creando un fichero, por ejemplo. Crear un flujo que permita al programador leer datos del teclado. Este flujo va a ser de entrada o lectura de datos y va a modelarse con una objeto de la clase InputStreamReader. El filtro para lectura de datos se modela con un objeto de la clase java.io.BufferedReader y el método de lectura adecuado va a ser String readLine() que genera una excepción del tipo IOException que debe ser gestionada correctamente en nuestra aplicación. Inicialmente la gestionaremos mediante la cláusula throws IOException a continuación del método main.
Conclusión final: El flujo u objeto InputStreamReader es lo que permite leer datos. El System.in u objeto InputStream es el argumento del constructor de InputStreamReader y modela el origen de los datos que se leen, es decir, el teclado.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
El filtro u objeto BufferedReader permite, mediante la utilización del método String readLine(), leer de forma óptima del flujo. Vamos a visualizar un ejemplo práctico para poder leer datos del teclado enviados por el usuario. Nos crearemos una clase que nos pida un nombre y devolveremos un saludo. import java.io.*; public class LecturaTeclado { public static void main(String[] args) throws IOException { System.out.println("Introduzca un nombre:"); BufferedReader lector=new BufferedReader(new InputStreamReader(System.in)); String nombreusuario; nombreusuario = lector.readLine(); System.out.println("Bienvenido a nuestra aplicacion: " + nombreusuario); } }
Resultado del programa:
Vemos que como resultado, hemos escrito el nombre de Lucia y hemos mostrado un mensaje. La excepción IOException que genera el método readLine() la hemos capturado mediante la palabra reservada throws, que veremos en capitulos posteriores del curso.
Ver Video: Analizar objeto String, en la Unidad 5, en el Módulo 1, en la plataforma elearning Laboratorio: Validación Email. Objetivo Conocer las ventajas de los métodos de la clase String y su uso como objeto.
Enunciado Nos crearemos una clase en Java llamada ValidacionMail. Dicha clase tendrá implementado en el código main la lógica para validar un email, teniendo en cuenta las siguientes restricciones de validación:
Un mail debe contener arroba La arroba no puede estar ni al principio ni al final. www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
No puede contener más de una arroba El correo debe contener un punto No puede haber dos puntos seguidos El punto y la arroba no pueden estar juntos ni por delante ni por detrás. Email sin espacios El dominio deberá ser dos a cuatro caracteres como máximo.
Pediremos al usuario el email por teclado. Mostraremos mensajes informativos personalizados por cada fallo que exista en el mail.
SOLUCIÓN CÓDIGO JAVA import java.io.*; public class ValidacionEmail { public static void main(String[] args) throws IOException { String email; BufferedReader lector=new BufferedReader(new InputStreamReader(System.in)); System.out.println("Escriba su email para la validacion"); email = lector.readLine(); int posicionarroba, posicionpunto, longitud; longitud = email.length(); posicionarroba = email.indexOf("@"); posicionpunto = email.indexOf("."); if (posicionarroba == -1) { System.out.println("No hay arroba en el mail"); } else if (posicionarroba == 0 || posicionarroba == longitud - 1) { System.out.println("La arroba no puede estar ni al principio ni al final"); } else if (posicionarroba != email.lastIndexOf("@")) { System.out.println("Existe mas de una @ dentro del mail"); } else if (posicionpunto == -1) www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
{ System.out.println("No hay punto en el mail"); } else if (posicionpunto == 0 || posicionpunto == longitud - 1) { System.out.println("El punto no puede estar ni al principio ni al final"); } else if (email.indexOf("..") != -1) { System.out.println("No pueden existir dos puntos seguidos"); } else if (email.indexOf("@.") != -1 || email.indexOf(".@") != -1) { System.out.println("El punto no puede ir seguido de la @"); } else if (email.indexOf(" ") != -1) { System.out.println("Un email no puede contenter espacios"); } else {
String dominio; int ultimopunto; ultimopunto = email.lastIndexOf("."); dominio = email.substring(ultimopunto + 1); if (dominio.length() >=2 && dominio.length() <=4) { System.out.println("EMAIL CORRECTO"); }else { System.out.println("El dominio solo puede ser de 2 a 4
caracteres"); } }
}
Actividades “Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades que encontrará en la unidad correspondiente de la plataforma eLearning”.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 6. Usando operadores y constructores Introducción Como cualquier lenguaje de programación, Java proporciona una serie de operadores que nos permiten llevar una lógica en el momento de realizar cualquier tipo de aplicación. Dichos operadores tienen una sintaxis específica dentro del lenguaje y nos pueden permitir desde preguntar por el estado de variables, hasta hacer un recorrido por todos los elementos de un conjunto para visualizar paso a paso cada uno de los elementos.
Objetivos
Aprender los diferentes operadores que proporciona el lenguaje Java.
Conocer el significado de la palabra constructor en una clase y sus posibles utilizaciones.
Operadores y expresiones Los operadores son un tipo de “tokens” o “símbolos” que indican una evaluación o computación para ser realizada en objetos o datos, y en definitiva sobre identificadores, constantes o variables. Además de realizar la operación, un operador devuelve un valor, ya que son parte fundamental de las expresiones. El valor y tipo que devuelve depende del operador y del tipo de sus operandos. Por ejemplo, los operadores aritméticos devuelven un número como resultado de su operación. Los operadores realizan alguna función sobre uno, dos o tres operandos, dependiendo del tipo de expresión en el que se utilicen. Los operadores que requieren un operando son llamados operadores unarios. Por ejemplo, el operador "++" es un operador unario que incrementa el valor de su operando en una unidad. Los operadores unarios en Java pueden utilizar tanto la notación prefija como la posfija. La notación prefija indica que el operador aparece antes que su operando. ++contador // Notación prefija, se evalúa a: contador+1 La notación posfija indica que el operador aparece después de su operando: contador++ // Notación posfija, se evalúa a: contador Los operadores que requieren dos operandos se llaman operadores binarios. Por ejemplo el operador "=" es un operador binario que asigna el valor del operando del lado derecho al operando del lado izquierdo. Todos los operadores binarios en Java utilizan notación infija, lo cual indica que el operador aparece entre sus operandos. operando1 operador operando2 Por último, los operadores ternarios son aquellos que requieren tres operandos. El lenguaje Java tiene el operador ternario, "?":, que es una sentencia similar a if-else. Este operador ternario usa notación infija; y cada parte del operador aparece entre operandos: expresión ? operación1 : operación2 Los operadores de Java se pueden dividir en las siguientes cuatro categorías: www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Aritméticos. Comparación y relacionales. A nivel de bits y lógicos. Asignación.
Operadores Aritméticos (Suma, resta, multiplicación, división, resto, incremento y decremento). Los operadores aritméticos se usan para realizar cálculos de aritmética entre variables y el resultado siempre será un valor que devuelven cómo resultado de su operación. En la siguiente tabla tenemos las operaciones aritméticas que podemos realizar entre dos operadores. Operador + * / %
Uso op1 op1 op1 op1 op1
+ op2 - op2 * op2 / op2 % op2
Descripción Suma op1 y op2 Resta op2 y op1 Multiplica op1 y op2 Divide op1 y op2 Obtiene el resto de la división de op1 y op2
Actúan sobre enteros y números en coma flotante. El operador + también se utiliza para concatenar cadenas (strings). En la siguiente tabla tenemos las operaciones aritméticas sobre un solo operando. Operador ++
Uso op++
++
++op
--
op--
--
--op
Descripción Incrementa op en 1; evalúa el valor antes de incrementar Incrementa op en 1; evalúa el valor después de incrementar Decrementa op en 1; evalúa el valor antes de decrementar Decrementaop en 1; evalúa el valor después de decrementar
Operadores Relacionales. Con operador relacional entendemos la relación que tiene un valor respecto a otro. Se basan en el concepto de verdadero o falso y en todos los casos operan con sólo dos estados diversos (0/1, encendido/apagado, verdadero/falso). Los operadores relacionales, como ya hemos dicho, producen un resultado 1 si la relación es verdadera, y 0 si la relación es falsa. Es importante comprender que el resultado de salida está constituido sólo por dos valores a fin de evitar confusiones entre el operador de asignación y el de igualdad. Operador > >= ‹ ‹= == !=
Uso op1>op2 op1>=op2 op1‹op2 op1‹=op2 op1==op2 op1!=op2
Devuelve true si op1 es mayor que op2 op1 es mayor o igual que op2 op1 es menor que op2 op1 es menor o igual que op2 op1 y op2 son iguales op1 y op2 son distintos
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Operadores Condicionales. El operador condicional sirve para tomar decisiones entre dos o más expresiones simples de comparación. Proporciona un resultado verdadero o falso entre dos o más posibilidades en función de una condición. Operador && || ! & |
Uso op1 && op2 op1 || op2 ! op op1 & op2 op1 | op2
Devuelve true si op1 y op2 son true (op2 lo evalúa si op1 es cierto) op1 o op2 es true (op2 lo evalúa si op1 es falso) op es false op1 y op2 son true, siempre evalúa op1 y op2 op1 o op2 es true, siempre evalúa op1 y op2
Operadores a nivel de bit En determinadas ocasiones nos puede interesar manipular datos a nivel de bit; por ejemplo activar o desactivar flags. Un flag es una “variable”' que puede tomar 2 valores, por lo que se suele representar con un bit. Debido a que en la mayoría de lenguajes de programación no existen tipos predefinidos de un bit, lo que se suele hacer es agrupar varios flags en una variable de tipo entero (“int”' o el tipo que queramos). Para acceder a estos flags o simplemente para activarlos es necesario utilizar operadores a nivel de bit. Operador >>
Uso op1 >> op2
‹‹
op1 ‹‹ op2
>>>
op1 >>> op2
& | ^ ~
op1 & op2 op1 | op2 op1 ^ op2 ~op2
Operación Desplaza los bits de op1 a la derecha tantas veces como indique op2. Rellena los huecos que queda con el bit de signo. Desplaza los bits de op1 a la izquierda tantas veces como indique op2. Rellena los huecos que queda con 0. Desplaza los bits de op1 a la derecha tantas veces como indique op2. Rellena los huecos que queda con 0. función and función or función xor complemento
Es interesante observar que la función AND a nivel de bits es igual que el operador condicional &. La diferencia está en los tipos de datos con los que se usa (Sobrecarga de operadores). - La función AND se usa con datos numéricos. - El operador condicional se usa sobre booleanos.
Operadores de asignación. Los operadores de asignación cambian el valor de una variable o de un objeto a otro valor, asignando o reasignándoles un nuevo valor. En la siguiente tabla podemos visualizar los operadores de asignación de Java. Operador += -= *= /= %= &= |= ^=
Uso op1 op1 op1 op1 op1 op1 op1 op1
+= op2 -= op2 *= op2 /= op2 %= op2 &= op2 |= op2 ^= op2
Equivale a op1 = op1 op1 = op1 op1 = op1 op1 = op1 op1 = op1 op1 = op1 op1 = op1 op1 = op1
+ op2 - op2 * op2 / op2 % op2 & op2 | op2 ^ op2
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
‹‹= >>= >>>=
op1 ‹‹= op2 op1 >>= op2 op1 >>>= op2
op1 = op1 ‹‹ op2 op1 = op1 >> op2 op1 = op1 >>> op2
Operador ternario if-then-else Es un operador que permite realizar una pregunta verdadero o falso, realizando una acción para cuando devuelve verdadero y otra acción para cuando devuelve falso. Solamente se puede realizar una acción para cada valor devuelto en la expresión, es decir, solamente puede haber una acción para verdadero y otra para falso. Aunque su sintaxis es confusa: Expresión ? sentencia 1 : sentencia 2 Su interpretación es sencilla: Si la expresión devuelve como resultado true entonces se ejecuta la sentencia 1, en caso contrario, se ejecuta la sentencia 2. Vamos a visualizar un ejemplo para comprender la expresión y su sintaxis. Compararemos un número y mostraremos si el número es positivo o negativo utilizando éste operador ternario. public class ClaseIfTernario { public static void main(String args[]) { int i=5; String mensaje; mensaje = i>=5?"Positivo":"Negativo"; System.out.println("El mensaje es " + mensaje); } } Comprobaremos que evalua la expresión y entra en la primera opción debido a que el número es positivo. Podremos comprobar que entra por el mensaje siguiente si cambiamos el valor de la variable a negativo.
Precedencia entre operadores. Los operadores de preferencia indican al compilador de Java cómo deseamos que se evalúe una expresión utilizando los paréntesis ( ). Un ejemplo nos servirá para aclarar el concepto: Podriamos escribir: x + y / 100 Si indicamos explícitamente al compilador el orden en el que queremos que se realicen las operaciones, él decide basándose en la precedencia asignada a los operadores y otros elementos que se utilizan dentro de una expresión. www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Los operadores con una precedencia más alta se evalúan primero. Por ejemplo, el operador división tiene una precedencia mayor que el operador suma, por eso, en la expresión anterior x + y / 100, el compilador evaluará primero el símbolo de división entre 100. Así x + y / 100 es equivalente a. x + (y / 100) pero si deseamos realizar otra operación antes, debemos indicarla de forma explicita: (x + y) / 100. El orden de precedencia se refleja en la siguiente tabla (de más prioritario a menos). Operadores posfijos Operadores unarios Creacion o cast aritmeticos Suma o resta Comparacion Relacional Igualdad AND negación OR OR AND logico OR lógico Condicional asignación
[] . (params) expr++ expr-++expr --expr +expr -expr ~ ! new (type)expr */% +‹‹> ‹ > ‹= >= instanceof == != & ^ | && || ?: = += -= *= /= %= &= ^= |= ‹‹= >>= >>>=
Sentencia return La sentencia return devuelve un valor desde un método. Cuando el programa Java lee dicha sentencia, inmediatamente finaliza la ejecución de la acción para retornar el valor final del conjunto de acciones. También sirve como sentencia para salir de un bucle. A diferencia de continue o break, la sentencia return también nos permite salir de un método o una función, elementos que no tienen ni break ni continue en bucles. for (int i=0; i<10; i++) { //ACCIONES return; } En el caso de que la función o método devuelva algún objeto o variable como resultado de una serie de operaciones, éste valor de la variable se tendrá que poner a continuación de la sentencia return. public int miMetodo() { int numero = 0; //ACCIONES return numero;. }
Sentencias de excepción, bloques try, catch, finally. www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Java incorpora en el propio lenguaje la gestión de errores mediante instrucciones de código. El mejor momento para detectar los errores es durante la compilación. Sin embargo prácticamente sólo los errores de sintaxis son detectados en esta operación. El resto de problemas surgen durante la ejecución de los programas. En el lenguaje Java, una Exception es un cierto tipo de error o una condición anormal que se ha producido durante la ejecución de un programa. Algunas excepciones son fatales y provocan que se deba finalizar la ejecución del programa. En este caso conviene terminar ordenadamente y dar un mensaje explicando el tipo de error que se ha producido. Otras excepciones, como por ejemplo no encontrar un fichero en el que hay que leer o escribir algo, pueden ser recuperables. En este caso el programa debe dar al usuario la oportunidad de corregir el error (definiendo por ejemplo un nuevo path del fichero no encontrado). Los errores se representan mediante clases derivadas de la clase Throwable, pero los que tiene que chequear un programador derivan de Exception (java.lang.Exception que a su vez deriva de Throwable). Existen algunos tipos de excepciones que Java obliga a tener en cuenta. Esto se hace mediante el uso de bloques try, catch y finally. El código dentro del bloque try está “vigilado”. Si se produce una situación anormal y se lanza como consecuencia una excepción, el control pasa al bloque catch, que se hace cargo de la situación y decide lo que hay que hacer. Se pueden incluir tantos bloques catch como se desee, cada uno de los cuales tratará un tipo de excepción. Finalmente, si está presente, se ejecuta el bloque finally, que es opcional, pero que en caso de existir se ejecuta siempre, sea cual sea el tipo de error. En el caso en que el código de un método pueda generar una Exception y no se desee incluir en dicho método la gestión del error (es decir los bucles try/catch correspondientes), es necesario que el método pase la Exception al método desde el que ha sido llamado. Esto se consigue mediante la palabra throws seguida del nombre de la Exception concreta, después de la lista de argumentos del método. A su vez el método superior deberá incluir los bloques try/catch o volver a pasar la Exception. De esta forma se puede ir pasando la Exception de un método a otro hasta llegar al último método del programa, el método main(). Vamos a visualizar las dos opciones que podemos incluir para controlar la excepción en un método: public class ControlExcepciones { public static void main(String[] args) { int num1, num2, resultado; num1 = 12; num2 = 0; resultado = num1 / num2; System.out.println("El resultado de la operacion es: " + resultado); } } Vamos a lanzar una excepción en el programa en el que estamos dividiendo un número entre cero. Como podemos comprobar, el programa nos da una excepción después de haberlo compilado, en ejecución. La excepción que debemos tratar en éste caso en concreto es ArithmeticException.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Para controlar la excepción podemos realizar el control de dos formas diferentes como hemos aprendido en la teoría. Mediante bloques try/catch. Nos permiten controlar la excepción y “personalizar” que deseamos realizar en el caso de que la excepción ocurra. public class ControlExcepciones { public static void main(String[] args) { try { int num1, num2, resultado; num1 = 12; num2 = 0; resultado = num1 / num2; System.out.println("El resultado de la operacion es: " + resultado); }catch (ArithmeticException ex) { System.out.println("No se puede dividir entre CERO"); System.out.println("Excepcion: " + ex); } } } La variable ex es una variable declarada únicamente para controlar la excepción ArithmeticException, en el caso de que suceda una excepción, dicha variable contiene las características de la excepción y lógicamente, solo se puede utilizar dentro del bloque catch.
La otra forma de controlar la excepción es mediante la clausula throws en el método. Dicho control de excepciones nos permite derivar excepciones, pero no nos permite personalizar la excepción, simplemente está capturada en el caso de que suceda. public class ControlExcepciones { public static void main(String[] args) throws ArithmeticException www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
{ int num1, num2, resultado; num1 = 12; num2 = 0; resultado = num1 / num2; System.out.println("El resultado de la operacion es: " + resultado); }
}
El resultado de la compilación es el mismo que si no controlamos la excepción, la diferencia radica en que si alguna clase utiliza nuestro método main, deberá controlar la excepción ArithmeticException. Es lo que se llama derivación de excepciones.
Ver Video: Operadores Pares, en la Unidad 6, en el Módulo 1, en la plataforma elearning Laboratorio: Averiguar día de nacimiento de la semana. Objetivos Aprender a manejar los operadores de Java.
Enunciado Pedir una fecha al usuario para calcular el día de la semana que nació. Tenemos que tener la tabla de días de la semana para la correspondencia comenzando en sábado: DIA
NÚMERO
Sábado
0
Domingo Lunes Martes Miércoles Jueves Viernes
1 2 3 4 5 6
Debemos tener el día, el número de mes y el año que el usuario haya nacido. A partir de esto datos hay que calcular lo siguiente para averiguar el día de la semana de nacimiento: Ejemplo = 22/06/1983 Hay que tener en cuenta el mes para realizar el cálculo, si el mes es Enero, el Mes será 13 y restaremos uno al año. Si el Mes es Febrero, el Mes será 14 y restaremos uno al año. Para poder calcular las el número final de la semana debemos seguir los siguientes pasos: 1. Multiplicar el Mes más 1 por 3 y dividirlo entre 5 ((6 + 1) * 3) / 5 = 4 2. Dividir el año entre 4 www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
1983 / 4 =495 3. Dividir el año entre 100 1983 / 100 = 19 4. Dividir el año entre 400 1983 / 400 = 4 5. Sumar el dia, el doble del mes, el año, el resultado de la operación 1, el resultado de la operación 2. Restar el resultado de la operación 3 y sumar finalmente la operación 4 más 2. 22 + (6 * 2) + 1983 + 4 + 495 - 19 + 4 + 2 = 2503 6. Dividir el resultado anterior entre 7. 2503 / 7 = 357 7. Restar el número del paso 5 con el número del paso 6 por 7. 2503 – (357 * 7) = 4 8. Miramos la tabla y vemos que el número 4 corresponde a Miércoles
Solución: CÓDIGO JAVA import java.io.*; public class ClaseDiaNacimiento { public static void main(String[] args) throws IOException { System.out.println("Introduzca su fecha de nacimiento (dd/mm/yyyy)"); BufferedReader lector=new BufferedReader(new InputStreamReader(System.in)); int mes, dia, anyo; String datomes, datodia, datoanyo; String fecha = lector.readLine(); int posicion = fecha.indexOf("/"); datodia = fecha.substring(0 , posicion); fecha = fecha.substring(posicion + 1); posicion = fecha.indexOf("/"); datomes = fecha.substring(0 , posicion); fecha = fecha.substring(posicion + 1); datoanyo = fecha; dia = Integer.parseInt(datodia); mes = Integer.parseInt(datomes); anyo = Integer.parseInt(datoanyo); if (mes == 1) { mes = 13; anyo--; www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
} if (mes == 2) { mes = 14; anyo--; } //Multiplicar el Mes más 1 por 3 y dividirlo entre 5 int ope1, ope2, ope3, ope4, ope5, ope6, ope7; ope1 = ((mes + 1) * 3) / 5; System.out.println("Operacion 1: " + ope1); //Dividir el año entre 4 ope2 = anyo / 4; System.out.println("Operacion 2: " + ope2); //Dividir el año entre 100 ope3 = anyo / 100; System.out.println("Operacion 3: " + ope3); //Dividir el año entre 400 ope4 = anyo / 400; System.out.println("Operacion 4: " + ope4); //Sumar el dia, el doble del mes, el año, //el resultado de la operación 1, el resultado de la operación 2 //, menos el resultado de la operación 3 más la operación 4 más 2. ope5 = dia + (mes * 2) + anyo + ope1 + ope2 + ope4 + 2 - ope3; System.out.println("Operacion 5: " + ope5); //Dividir el resultado anterior entre 7. ope6 = ope5 / 7; System.out.println("Operacion 6: " + ope6); //Restar el número del paso 5 con el número del paso 6 por 7. ope7 = ope5 - (ope6 * 7); System.out.println("Operacion 7: " + ope7); String resultado = ""; //Miramos la tabla y vemos que el número 4 corresponde a Miércoles switch (ope7) { case 0: resultado break; case 1: resultado break; case 2: resultado break; case 3: resultado break; case 4: resultado break; case 5: resultado break; case 6: resultado break;
= "Sabado"; = "Domingo"; = "Lunes"; = "Martes"; = "Miercoles"; = "Jueves"; = "Viernes";
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
} System.out.println("--------------------------------------------------------"); System.out.println("--------------------------------------------------------");
}
System.out.println("El dia de la semana de su nacimiento fue: " + resultado); System.out.println("--------------------------------------------------------"); System.out.println("Fin de programa"); lector.readLine();
}
Actividades “Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades que encontrará en la unidad correspondiente de la plataforma eLearning”.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 7. Usando Loops Introducción Dentro de cualquier lenguaje de programación existen una serie de estructuras que nos permiten poder definir una lógica no lineal para trabajar en la aplicación. En cualquier programa aparecen a menudo preguntas que necesitamos responder para que la aplicación realice una acción determinada u otra. Mediante las sentencias podemos realizar dicha lógica y responder a las preguntas que vayan apareciendo dentro de un programa para hacer una secuencia o una evaluación de variables.
Objetivo
Manejar las sentencias condicionales que nos proporciona el lenguaje Java.
Utilización de sentencias iterativas para solucionar problemas de lógica en aplicaciones.
Sentencia if-else Permite seleccionar la ejecución de distintos fragmentos de código dependiendo del resultado de la valoración de una expresión booleana. Su sintaxis es la siguiente: if (expresion_booleana 1) { // La expresión booleana expresa condiciones ... // código que se ejecuta si la expresión devuelve true ... } else if (expresión boolean 2) { ... // código que se ejecuta si la expresión devuelve true ... } else { // código que se ejecuta si la expresión devuelve false } El uso de else es opcional. La expresión booleana puede contener operadores relacionales para encadenar condiciones. Vamos a visualizar un ejemplo práctico en el que compararemos el valor de una variable utilzando If, Else y Else If: public class ClaseIfElse { public static void main(String args[]) { int i=0; String mensaje=""; if (i>0) { mensaje = "Positivo"; }else if (i<0) { mensaje = "Negativo"; }else { mensaje = "Cero"; www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
} System.out.println("El valor de i es " + mensaje); } } Comprobaremos que entra en el último IF debido a que ya ha evaluado el resto de expresiones que hemos escrito en las condiciones del código.
Sentencia switch-case Se utiliza cuando se quieren analizar muchas posibilidades de una única variable o expresión. Su sintaxis es la siguiente: switch (expresión) { case valor1: sentencias1; break; case valor2: sentencias2; break; case valor3: sentencias3; break; case valor4: sentencias4; break; default: sentencias_default break; } La expresión puede devolver cualquier tipo básico, y cada uno de los valores especificados en las sentencias case debe ser un tipo compatible. La sentencia default es opcional y se ejecutará en todos los casos en el que el valor devuelto por expresión no coincida con los especificados en los case. La sentencia break (sin etiqueta) hace que se salga del dominio de la sentencia switch. Con ello se evita que se valoren todas las opciones que quedan una vez que se ha encontrado la correcta. Es opcional. Se leeran todas las sentencias en cascada hasta que encuentre un break para cortar la ejecución de las acciones. Vamos a visualizar un ejemplo en el evaluaremos una variables entera y mostraremos un mensaje dependiendo del valor obtenido en los diferentes casos que escribamos en el programa. public class EjemploSwitch www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
{ public static void main(String args[]) { String mensaje=""; int i=2; switch (i) { case 0: mensaje = "El número es cero"; break; case 1: mensaje = "El número es uno"; break; case 2: mensaje = "El número es dos"; break; case 3: mensaje = "El número es tres"; break; case 4: case 5: case 6: mensaje = "El número es cuatro, cinco o seis"; break; default: mensaje = "El número es otro no evaluado"; } System.out.println("He salido del Switch"); System.out.println("El mensaje es " + mensaje); } } Como resultado de la aplicación visualizaremos:
Podremos ir cambiando el valor de la variable para ir visualizando las diferentes opciones y el comportamiento de la expresión condicional switch.
Sentencia while Ejecuta repetidamente un conjunto de sentencias mientras una expresión booleana sea verdadera. Su sintaxis es:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
while (Expresión_booleana) { //Condición de permanencia ... sentencias; ... } Dentro del bucle se deberá alterar la variable que controla el bucle de lo contrario nunca se dejará de cumplir la condición. Se puede realizar un bucle infinito si no se incluye una salida dentro del bucle para finalizar su ejecución. Para visualizar el comportamiento del bucle while vamos a crearnos un ejemplo práctico en el que incrementaremos una variable entera. public class EjemploWhile { public static void main(String args[]) { String mensaje=""; int i=0; while (i <= 10) { i++; System.out.println("Valor de i: " + i); } } } Podemos comprobar que la ejecución del programa permanece en el bucle hasta que la variable alcanza la condición deseada.
Sentencia do-while Igual que la sentencia while, pero las sentencias se ejecutan al menos una vez antes de valorar las expresión, eso nos permite saber que al menos se ejecutará la sentencia del bucle una vez, permitiéndonos evaluar posteriormente. Su sintaxis:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
do { ... sentencias; ... } while (Expresión_booleana);
Vamos a realizar un ejemplo práctico para visualizar el comportamiento de éste tipo de sentencia. Lo que haremos será crearnos una variable con valor superior a la condición del bucle y podremos comprobar que primero entra en el bucle y después evalua el valor de la variable creada. public class EjemploDoWhile { public static void main(String args[]) { String mensaje=""; int i=20; System.out.println("Estoy al inicio del bucle"); do { i++; System.out.println("Valor de i: " + i); }while (i <= 10); System.out.println("Fin del bucle"); } } La acción se realiza al menos una vez, que es la principal característica de éste tipo de bucle.
Sentencia for Este bucle permite establecer la inicialización de la variable que controla el bucle, su variación y la condición de permanencia, en la propia definición del for. Es un bucle numérico, por lo que su condición de salida se establece en el número de veces que estará dentro del bucle, permitiéndonos controlar totalmente el número exacto de repeticiones en las que se realizará una misma acción. Su sintaxis:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
for (inicialización; condición de permanencia; variación){ ... sentencias ...
}
La inicialización hace referencia a la variable de control del bucle. La condición de permanencia es una expresión booleana donde debe encontrarse la variable de control. La actualización hace referencia a la variable de control. Vamos a visualizar un ejemplo en el que mostraremos los números pares que hay entre 0 y 20. Para ello utilizaremos un bucle contador debido a que sabemos el número exacto de veces que tiene que repetir la acción: public class EjemploFor { public static void main(String args[]) { System.out.println("Estoy al inicio del bucle"); System.out.println("Numeros pares"); for (int i=0; i<20;i++) { if (i%2==0) { System.out.println("Valor de i: " + i); } } System.out.println("Fin de programa"); } }
Existen múltiples combinaciones, también podríamos cambiar el incremento del bucle para que realice la acción de dos en dos y no evalue el valor de la variable. public class EjemploFor { public static void main(String args[]) { www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
System.out.println("Estoy al inicio del bucle"); System.out.println("Numeros pares"); for (int i=0; i<20;i+=2) { System.out.println("Valor de i: " + i); } System.out.println("Fin de programa"); }
}
Podremos comprobar que la ejecución es la misma en el programa:
Ver Video: Validar ISBN, en la Unidad 7, en el Módulo 1, en la plataforma elearning Laboratorio: Conjetura Collatz Objetivo Aprender a manejar las sentencias condicionales y los bucles.
Enunciado Crear una aplicación en la que validaremos la secuencia de Collatz. Pediremos un número al usuario y debemos representar todos la secuencia de números de Collatz para comprobar que es correcta. La conjetura de Collatz es una regla matemática y su teoría es la siguiente: Todo número entero mediante una secuencia llegará a ser 1. Si el número entero es par, lo divideremos entre 2. Si el número entero es impar, lo multiplicaremos por 3 y le sumaremos uno al resultado. Siguiendo ésta secuencia, debemos llegar al número uno para todo número entero. Debemos pedir números al usuario hasta que introduzca por teclado un valor numérico, si introduce una letra, debemos pedirle de nuevo otro número hasta que nos ofrezca un valor correcto.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Solución: CÓDIGO JAVA Imports System.Threading import java.io.*; public class ConjeturaCollatz { public static void main(String[] args) { boolean esnumero = false; int numero = 1; do { try { System.out.println("Introduzca un numero...."); BufferedReader lector=new BufferedReader(new InputStreamReader(System.in)); String dato = lector.readLine(); numero = Integer.parseInt(dato); esnumero = true; }catch (Exception ex) { esnumero = false; } }while (esnumero==false); System.out.println("SECUENCIA DE COLLATZ"); System.out.println("--------------------------"); while (numero!=1) { if (numero%2==0) { numero = numero / 2; }else{ numero = (numero * 3) + 1; } System.out.println(numero); } System.out.println("Fin de programa"); } }
Actividades
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
“Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades que encontrará en la unidad correspondiente de la plataforma eLearning”.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 8. Desarrollando y usando métodos Introducción Los métodos son acciones que se realizan sobre un objeto determinado. importante en el momento de utilizar o crear cualquier objeto.
Son una parte muy
Si ponemos como ejemplo cualquier objeto del mundo real, descubriremos que tiene unos métodos que accionamos y que realizan acciones. Poniendo el ejemplo de un coche, dicho objeto contiene las acciones de arrancar, frenar o girar. Esos métodos nos llevan a poder controlar el objeto y manejarlo. En programación y en el lenguaje Java sucede lo mismo con cualquier objeto que necesitemos, podremos realizar acciones sobre él para controlar la actividad de nuestra aplicación.
Objetivos
Aprender el concepto de método dentro del lenguaje Java.
Conocer las ventajas de aplicar métodos en las clases, así como realizar llamadas a métodos creados en clases referenciadas y static.
Métodos (Funciones Miembro) Los métodos son acciones que se realizan sobre una clase o sobre un objeto, dependiendo de la declaración del método. Normalmente los métodos se pueden dividir en aquellos que son usados internamente dentro de la propia clase, llamados métodos privados (private), los que se utilizan fuera de la clase, llamados métodos públicos (public) y los que son usados por la clase y las clases que heredan de ellos, llamados métodos protegidos (protected). Los métodos privados son, generalmente, llamados en el interior del objeto por otras partes del mismo. Una vez que se tiene un objeto que soporta métodos, se pueden usar los métodos de esos objetos.
Métodos de objeto Los métodos son funciones definidas dentro de una clase. Salvo los métodos static o de clase, se aplican siempre a un objeto de la clase por medio del operador punto . Dicho objeto es su argumento implícito. Los métodos pueden tener otros argumentos explícitos que se introducen entre paréntesis, a continuación del nombre del método. La primera línea de la definición de un método se llama declaración o comprendido entre las llaves {} es el cuerpo o body del método.
cabecera; el código
Podemos verlo claramente con un ejemplo de la clase Coche: public string devolverModelo() { // header y comienzo del método return “BMW”; // body } // final del método La cabecera consta del ámbito de acceso (public,prívate o protected), del tipo del valor de devolución (un tipo de la clase string en este caso), del nombre del método y de una lista de
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
argumentos explícitos entre paréntesis, separados por comas. Si no hay argumentos explícitos se dejan los paréntesis vacíos (como en éste ejemplo exactamente). Los métodos tienen visibilidad directa de las variables miembro del objeto que es su argumento implícito, es decir, pueden acceder a ellas sin definirlas con un nombre de objeto y el operador punto (.). De todas formas, también se puede acceder a ellas mediante la referencia this. El valor de devolución puede ser un valor de un tipo primitivo o una referencia a otro objeto. En cualquier caso no puede existir más que un único valor de retorno (que puede ser un objeto o un array). Se puede devolver también una referencia a un objeto por medio de un nombre de variable. Se puede devolver como valor de retorno un objeto de la misma clase que el método o de una subclase, pero nunca de una superclase. Los métodos pueden definir variables locales. Su visibilidad llega desde la definición al final del bloque en el que han sido definidas. No es necesario inicializar las variables locales en el punto en que se definen, pero el compilador no permite utilizarlas sin haberles dado un valor inicial. A diferencia de las variables miembro, las variables locales no se inicializan por defecto. Vamos a visualizar un ejemplo en el que nos crearemos métodos de objeto. Tendremos varios métodos que devuelven un valor y otro método (void) que realizará una acción sin almacenar su valor: public class ClaseMatematicas { private double PI = 3.1416; public int dividirnumero(int numero, int divisor) { int resultado; resultado = numero / divisor; return resultado; } public int devolverCuadrado(int numero) { int resultado; resultado = numero * numero; return resultado; } public int devolverCubo(int numero) { int resultado; resultado = numero * numero * numero; return resultado; } public void mostrarPI() { System.out.println("Numero PI: " + this.PI); } } Ahora podemos probar los métodos que hemos creado en una clase: public class PruebaMetodos { public static void main(String[] args) { ClaseMatematicas c = new ClaseMatematicas(); www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
int num = 4; int resultado; System.out.println("El numero inicial es: " + num); resultado = c.dividirnumero(num, 2); System.out.println("El numero dividido entre dos es: " + resultado); resultado = c.devolverCuadrado(num); System.out.println("El cuadrado del numero es: " + resultado); resultado = c.devolverCubo(num); System.out.println("El cubo del numero es: " + resultado); c.mostrarPI(); }
}
Como podemos comprobar, los métodos que devuelven valor debemos almacenarlos en variables que corresponden con el valor devuelto (en nuestro ejemplo int). Mientras que los métodos void son métodos de acción y no es necesario almacenar su valor en ninguna variable.
Parámetros en los métodos En Java los argumentos de los tipos primitivos se pasan siempre por valor. El método recibe una copia del argumento actual. Si se modifica esta copia, el argumento original que se incluyó en la llamada no queda modificado. La forma de modificar dentro de un método una variable de un tipo primitivo es incluirla como variable miembro en una clase y pasar como argumento una referencia a un objeto de dicha clase. Las referencias se pasan también por valor, pero a través de ellas se pueden modificar los objetos referenciados. Dentro de un método se pueden crear variables locales de los tipos primitivos o referencias. Dichas variables locales dejan de existir al terminar la ejecución del método. Los argumentos formales de un método (las variables que aparecen en la cabecera del método para recibir el valor de los argumentos actuales) tienen ámbito de variables locales del método. Si un método devuelve this, es decir, un objeto de la clase o una referencia a otro objeto, ese objeto puede encadenarse con otra llamada a otro método de la misma o de diferente clase y así consecutivamente. Vamos a visualizar un ejemplo en el que enviaremos una variable a un método y modificaremos su valor, visualizando que el valor de dicha variable no cambiar, ya que estamos enviando el valor del objeto, no la referencia. Nos vamos a crear una clase llamada ClaseMatematicas e inlcuiremos un método llamado multiplicar que recibe un número como argumento. Lo que haremos será multiplicar el número por dos. public class ClaseMatematicas www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
{ public void multiplicar(int numero) { numero = numero * 2; } } A continuación nos crearemos una clase que implemente dicho método y le pasaremos un número como valor para visualizar el resultado: public class PruebaMetodos { public static void main(String[] args) { ClaseMatematicas c = new ClaseMatematicas(); int num = 33; c.multiplicar(num); System.out.println("El doble del numero es: " + num); } }
Como podemos comprobar, el número enviado no se modifica, solamente es modificado su valor, por lo que no se envía la referencia al objeto, sino su valor, lo que en realidad se está modificando y multiplicando es la variable llamada numero de la clase ClaseMatematicas. Para solucionar el problema, habría que crearse un método que devolviese un valor: public class ClaseMatematicas { public int multiplicar(int numero) { numero = numero * 2; return numero; } } Posteriormente, al utilizar el método, guardaríamos el valor de retorno dentro de una variable, en nuestro ejemplo es la misma variable: public class PruebaMetodos { public static void main(String[] args) { ClaseMatematicas c = new ClaseMatematicas(); int num = 33; System.out.println("El numero enviado es: " + num); num = c.multiplicar(num); System.out.println("El doble del numero es: " + num); } } www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Vemos que como resultado, la acción se realiza correctamente. Antes también estaba haciendo la acción correctamente, pero habíamos creado un método void y no devolvía ningún valor y la variable número quedaba encapsulada dentro de la clase.
Métodos sobrecargados (overloaded) Java permite métodos sobrecargados (overloaded), es decir, métodos distintos que tienen el mismo nombre, pero que se diferencian por el número y/o tipo de los argumentos. A la hora de llamar a un método sobrecargado, Java sigue unas reglas para determinar el método concreto que debe llamar:
Si existe el método cuyos argumentos se ajustan exactamente al tipo de los argumentos de la llamada (argumentos actuales), se llama ese método. Si no existe un método que se ajuste exactamente, se intenta promover los argumentos actuales al tipo inmediatamente superior (por ejemplo char a int, int a long, float a double, etc.) y se llama el método correspondiente. Si sólo existen métodos con argumentos de un tipo más restringido (por ejemplo, int en vez de long), el programador debe hacer un cast explícito en la llamada, responsabilizándose de esta manera de lo que pueda ocurrir. El valor de retorno no influye en la elección del método sobrecargado. En realidad es imposible saber desde el propio método lo que se va a hacer con él. No es posible crear dos métodos sobrecargados, es decir con el mismo nombre, que sólo difieran en el valor de retorno.
Diferente de la sobrecarga de métodos es la redefinición. Una clase puede redefinir (override) un método heredado de una superclase. Redefinir un método es dar una nueva definición. En este caso el método debe tener exactamente los mismos argumentos en tipo y número que el método redefinido. La sobrecarga de métodos es muy sencilla de visualizar en la práctica, es un método que se llama igual pero que tienen diferentes formas, expresadas en el número de argumentos y el tipo de argumentos que recibe el método. Por ejemplo, vamos a realizar una sobrecarga del método multiplicar de la clase matemáticas: public class ClaseMatematicas { public int multiplicar(int numero) { int resultado; resultado = numero * 2; return resultado; }
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
public int multiplicar(int numero, int multiplicador) { int resultado; resultado = numero * multiplicador; return resultado; } } Tenemos dos métodos con el mismo nombre, pero con diferentes argumentos. Cuando realicemos la llamada al método comprobaremos que entrará en el primer método cuando sólo reciba un parámetro y en el segundo cuando reciba dos parámetros. public class PruebaMetodos { public static void main(String[] args) { ClaseMatematicas c = new ClaseMatematicas(); int num = 9; System.out.println("El numero enviado es: " + num); int resultado; resultado = c.multiplicar(num); System.out.println("Resultado de multiplicar con un parametro: " + resultado); resultado = c.multiplicar(num, 9); System.out.println("Resultado de multiplicar con varios parametros: " + resultado); } } Como podemos comprobar en la pantalla de resultado, la acción de la aplicación leerá cada método de la ClaseMatematicas dependiendo de los argumentos que se le envíen en la llamada:
Métodos de clase (static) De la misma forma que existen métodos de objeto, puede también haber métodos que no actúen sobre objetos concretos a través del operador punto. A estos métodos se les llama métodos de clase o static. Los métodos de clase pueden recibir objetos de su clase como argumentos explícitos, pero no tienen argumento implícito ni pueden utilizar la referencia this ni Me. Un ejemplo típico de métodos static son los métodos matemáticos de la clase Math (sin(), cos(), abs(), pow(), etc.). El argumento de estos métodos será de un tipo primitivo y se le pasará como argumento explícito. Estos métodos no tienen sentido como métodos de objeto. Los métodos y variables de clase se crean anteponiendo la palabra static a la definición del método, igual que hemos visto que sucede con las variables miembro de una clase. Para llamarlos
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
se suele utilizar el nombre de la clase, en lugar del nombre de un objeto de la clase (por ejemplo, Math.sin(ang), para calcular el seno de un ángulo).
Métodos Constructores Un punto clave de la Programación Orientada Objetos es el evitar información incorrecta por no haber sido correctamente inicializadas las variables. Java no permite que existan variables miembro que no estén inicializadas Java inicializa con valores por defecto las variables miembro de clases y objetos. El paso correcto sería la inicialización de objetos en los constructores. Un constructor es un método que se llama automáticamente cada vez que se crea un objeto de una clase. La principal misión del constructor es reservar memoria e inicializar variables miembro de la clase. Los constructores no tienen valores de devolución y su nombre es el mismo que el de la clase. Su argumento implícito es el objeto que se está creando. Una clase puede contener varios constructores, que se diferencian por el tipo y número de sus argumentos, al igual que sucede con los métodos sobrecargados. Se llama constructor por defecto al constructor que no tiene argumentos. El programador debe proporcionar en el código valores iniciales adecuados para todas las variables miembro. Un constructor de una clase puede llamar a otro constructor previamente definido en la misma clase por medio de la palabra this. En este contexto, la palabra this sólo puede aparecer en la primera sentencia de un constructor. El constructor de una subclase puede llamar al constructor de su superclase por medio de la palabra super, seguida de los argumentos apropiados entre paréntesis. De esta forma, un constructor sólo tiene que inicializar por sí mismo las variables no heredadas. El constructor es tan importante que, si el programador no prepara ningún constructor para una clase, el compilador crea un constructor por defecto, inicializando las variables de los tipos primitivos a su valor por defecto, y los Strings y las demás referencias a objetos a null. Al igual que los demás métodos de una clase, los constructores pueden tener también los modificadores de acceso public, private, protected. Si un constructor es private, ninguna otra clase puede crear un objeto de esa clase. En este caso, puede haber métodos public y static que llamen al constructor y devuelvan un objeto de esa clase. Dentro de una clase, los constructores sólo pueden ser llamados por otros constructores o por métodos static. No pueden ser llamados por los métodos de objeto de la clase.
Destrucción de objetos En Java no existen destructores de memoria. El sistema se encarga automáticamente de liberar la memoria de los objetos que ya han perdido la referencia, es decir, objetos que ya no tienen ningún nombre que permita acceder a ellos. Al llegar al final de un bloque en el que habían sido definidos, porque a la referencia se le ha asignado el valor null o porque a la referencia se le ha asignado la dirección de otro objeto. A esta funcionalidad de Java se le llama garbage collection, recolección de basura. En Java es normal que varias variables de tipo referencia apunten al mismo objeto. Java lleva internamente un contador de cuántas referencias hay sobre cada objeto. El objeto podrá ser borrado cuando el número de referencias sea cero. Como ya se ha dicho, una forma de hacer que un objeto quede sin referencia es cambiar ésta a null, haciendo por ejemplo: ObjetoReferenciado = null;
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
En Java no se sabe exactamente cuándo se va a activar el garbage collector. Si no falta memoria es posible que no se llegue a activar en ningún momento. Se puede llamar explícitamente al garbage collector con el método System.gc(), aunque esto es sólo una sugerencia, ya que posteriormente, se le llamará de nuevo y no es conveniente realizar la llamada, ya que sería hacer la misma acción dos veces, una por nuestra llamada y otra por la llamada automática.
Métodos Finalizadores Los finalizadores son métodos que vienen a completar la labor del garbage collector. Un finalizador es un método que se llama automáticamente cuando se va a destruir un objeto, justo antes de que la memoria sea liberada de modo automático por el sistema. Se utilizan para ciertas operaciones de finalización distintas de liberar memoria, como podría ser cerrar ficheros que tengamos abiertos para la aplicación o cerrar conexiones de acceso a datos que hayamos abierto previamente. Un finalizador es un método de objeto sin valor de retorno, sin argumentos y que siempre se debe denominar con el nombre de finalize(). Los finalizadores se llaman de modo automático siempre que hayan sido definidos por el programador de la clase. Para realizar su tarea correctamente, un finalizador debería terminar siempre llamando al finalizador de su superclase. Tampoco se puede saber el momento preciso en que los finalizadores van a ser llamados.
Definición de métodos heredados (override) Una clase puede redefinir cualquiera de los métodos heredados de su superclase que no estén definidos como final. El nuevo método sustituye al heredado para todos los efectos en la clase que lo ha redefinido. Los métodos de la super-clase que han sido redefinidos pueden ser todavía accedidos por medio de la palabra super desde los métodos de la clase derivada, aunque con este sistema sólo se puede subir un nivel en la jerarquía de clases. Los métodos redefinidos pueden ampliar los derechos de acceso de la ejemplo ser public, en lugar de protected, pero nunca restringirlos.
superclase,
como por
Los métodos de clase o static no pueden ser redefinidos en las clases derivadas.
Clases y métodos abstractos Una clase abstracta (abstract) es una clase de la que no se pueden crear objetos. Su utilidad es permitir que otras clases deriven de ella, proporcionándoles un marco o modelo que deben seguir y algunos métodos de utilidad general. Las clases abstractas se declaran incluyendo la palabra abstract antes de su definición: public abstract class ClaseAbstracta { } Una clase abstracta puede contener métodos definidos como abstract, en cuyo caso no se implementa la acción del método, solamente se define su cabecera. Si una clase tiene algún método abstracto es obligatorio que la clase sea abstract. El hecho de definir un método como abstract implica que cualquier clase que herede de mi clase, deberá sobreescribir dicho método e implementarlo. Una clase abstracta puede contener métodos que no son abstractos. Dichos métodos son métodos de objeto como cualquier clase, deben tener una definición (cabecera) y una implementación (acción del método). Como los métodos static no pueden ser redefinidos, un método abstract no puede ser static.
Clases y métodos finales www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Debemos recordar que los miembros (variables) declarados como final no pueden cambiar su valor una vez que han sido inicializadas. Una clase declarada final no puede tener clases derivadas, es decir, no puede ser heredada. Esto se puede realizar por causas de seguridad y también por causas de eficiencia, debido a que cuando el compilador reconoce que los métodos no van a ser redefinidos puede hacer optimizaciones adicionales. Igualmente, un método declarado como final no puede ser redefinido por una clase que derive de su propia clase, es decir, no puede haber sobreescritura del método en sus clase derivadas.
Ver Video: Tipos de métodos, en la Unidad 8, en el Módulo 1, en la plataforma elearning Laboratorio: Creación del objeto Calculadora Objetivos Aprender los diferentes tipos de métodos que existen en la programación Java. Conocer las diferencias entre los constructores, métodos estáticos y métodos de objeto.
Enunciado Realizar una aplicación en la que podremos realizar operaciones sobre dos números pedidos al usuario. Crearemos una clase llamada Calculadora que podrá realizar todas las operaciones mediante métodos de objeto o estáticos, dependiendo de su funcionalidad. Las acciones como restar, multiplicar, sumar o dividir serán métodos de objeto y utilizarán las variables miembro de la Calculadora. Las acciones como mostrar número aleatorio o averiguar el número mayor entre varios números serán métodos static. Tendremos una sobrecarga en el método numero mayor que pedirá tres números. Crearemos dos constructores dónde inicializaremos los números miembros de la clase. Un constructor inicializará los datos a cero, mientras que otro constructor tendrá argumentos que inicializarán los miembros internos de la clase. Crearemos un método privado de la clase que comprobará si los datos enviados son números. Crearemos un método static para mostrar el menú de la calculadora: Menu Calculadora 1.2.3.4.5.6.7.8.9.0.-
Sumar Restar Dividir Multiplicar Resto Mayor 2 numeros Mayor 3 numeros Potencia Numero aleatorio SALIR
Seleccione una opción
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Crearemos una clase para comprobar que todo funciona y que los conceptos de métodos sobre la clase calculadora han quedado claros.
Solución: CÓDIGO JAVA CODIGO DE LA CLASE CALCULADORA public class Calculadora { public static final double PI = 3.141592; public int numero1; public int numero2; public Calculadora() { numero1 = 0; numero2 = 0; } public Calculadora(int num1, int num2) { numero1 = num1; numero2 = num2; } public void setNumero1(String dato) { if (this.comprobarNumero(dato)==true) { this.numero1 = Integer.parseInt(dato); }else { this.numero1 = 0; } } public int getNumero1() { return this.numero1; }
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
public void setNumero2(String dato) { if (this.comprobarNumero(dato)==true) { this.numero2 = Integer.parseInt(dato); }else { this.numero2 = 0; } } public int getNumero2() { return this.numero2; } public int sumarNumeros() { return numero1 + numero2; } public int restarNumeros() { return numero1 - numero2; } public int dividirNumeros() { return numero1 / numero2; } public int multiplicarNumeros() { return numero1 * numero2; } public int restoNumeros() { return numero1 % numero2; } public int numeroMayor() { if (numero1 > numero2) { return numero1; }else{ return numero2; } } public static int numeroMayor(int num1, int num2, int num3) { if (num1 > num2 && num1 > num3) { return num1; }else if (num2 > num1 && num2 > num3) www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
{ return num2; }else{ }
return num3;
} public static int calcularPotencia(int num, int potencia) { int resultado = 0; for (int i = 1; i < potencia; i++) { resultado += num * num; } return resultado; } public static int devolverAleatorio(int rangomaximo) { int resultado = (int)(Math.random() * rangomaximo); return resultado; } public static void mostrarMenu() { System.out.println("Menu Calculadora"); System.out.println("1.- Sumar"); System.out.println("2.- Restar"); System.out.println("3.- Dividir"); System.out.println("4.- Multiplicar"); System.out.println("5.- Resto"); System.out.println("6.- Mayor 2 numeros"); System.out.println("7.- Mayor 3 numeros"); System.out.println("8.- Potencia"); System.out.println("9.- Numero aleatorio"); System.out.println("0.- SALIR"); System.out.println("Seleccione una opcion"); } private boolean comprobarNumero(String dato) { try { int num = Integer.parseInt(dato); return true; }catch (Exception ex) { return false; } } }
CODIGO DE LA CLASE PRUEBACALCULADORA import java.io.*; public class PruebaCalculadora www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
{ public static void main(String[] args) throws IOException { BufferedReader lector=new BufferedReader(new InputStreamReader(System.in)); Calculadora c = new Calculadora(); System.out.println("Introduzca el numero 1"); String dato = lector.readLine(); c.setNumero1(dato); System.out.println("Introduzca el numero 2"); dato = lector.readLine(); c.setNumero2(dato); int opcion = 1; int resultado = 0; while (opcion != 0) { Calculadora.mostrarMenu(); opcion = Integer.parseInt(lector.readLine()); switch (opcion) { case 1: resultado = c.sumarNumeros(); break; case 2: resultado = c.restarNumeros(); break; case 3: resultado = c.dividirNumeros(); break; case 4: resultado = c.multiplicarNumeros(); break; case 5: resultado = c.restoNumeros(); break; case 6: resultado = c.numeroMayor(); break; case 7: int num1, num2, num3; System.out.println("Introduzca primer numero"); num1 = Integer.parseInt(lector.readLine()); System.out.println("Introduzca segundo numero"); num2 = Integer.parseInt(lector.readLine()); System.out.println("Introduzca tercer numero"); num3 = Integer.parseInt(lector.readLine()); resultado = Calculadora.numeroMayor(num1,num2,num3); break; case 8: System.out.println("Introduzca primer numero"); num1 = Integer.parseInt(lector.readLine()); System.out.println("Introduzca segundo numero"); num2 = Integer.parseInt(lector.readLine()); resultado = Calculadora.calcularPotencia(num1,num2); break; case 9: System.out.println("Introduzca el rango maximo del numero"); num1 = Integer.parseInt(lector.readLine()); www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
resultado = Calculadora.devolverAleatorio(num1); break; } System.out.println("---------------------------------"); System.out.println("El resultado de la operacion es: " + resultado); } System.out.println("---------------------------------"); System.out.println("Numero PI: " + Calculadora.PI); System.out.println("Fin de programa"); } }
Actividades “Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades que encontrará en la unidad correspondiente de la plataforma eLearning”.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 9. Implementando encapsulación Introducción La encapsulación es un concepto muy simple. No dejaremos ver ningún elemento que no deseamos que sea visualizado. Dentro del mundo real tenemos muchos ejemplos que nos pueden llegar a hacer comprender dicho concepto. Cuando utilizamos un móvil, todo el mundo sabe teclear los números en la pantalla para poder llamar a un número, pero la mayoría no sabemos el proceso que se realiza internamente para poder comunicarse con la otra persona a quién llamamos. Esto sucede porque quién ha creado el móvil no vió necesario que supiéramos los mecanismos internos que se necesitan para realizar una llamada, solamente nos “ofreció” la forma de utilizar un móvil, no como funciona internamente ya que no era necesario para nosotros. El mismo concepto puede ser aplicado a la programación. Mediante una serie de palabras clave y conceptos, podemos “ocultar” al usuario cómo hemos realizado las acciones, simplemente le dejaremos manejarlas, pero sin que conozca nuestro código ni nuestros trucos.
Objetivos
Comprender los conceptos fundamentales de la programación orientada a objetos con la encapsulación de miembros y métodos.
Aplicar los conocimientos adquiridos durante el curso para proteger las variables y métodos de otras clases.
Paquetes Un paquete es una colección de clases e interfaces relacionadas. El compilador de Java usa los paquetes para organizar la compilación y ejecución. Es decir, un paquete es una biblioteca. De hecho el nombre completo de una clase es el nombre del paquete en el que está la clase, punto y luego el nombre de la clase. Es decir si la clase Coche está dentro del paquete mediotransporte, el nombre completo de Coche es mediotransporte.Coche. A veces resulta que un paquete está dentro de otro paquete, entonces habrá que indicar la ruta completa a la clase, como si fuera un sistema de archivos de un sistema operativo (para entrar en una subcarpeta, primero debemos pasar por la primera carpeta, el hecho de abrir una carpeta no quiere decir que estemos visualizando los ficheros que existen en alguna otra subcarpeta). Mediante el comando import, se evita tener que colocar el nombre completo. El comando import se coloca antes de definir la clase, fuera del código de la clase como primera instrucción. Por Ejemplo: import mediotransporte.Coche; Debido a esta instrucción para utilizar la clase Coche no hace falta indicar el paquete en el que se encuentra, basta indicar sólovCoche. Se puede utilizar el símbolo asterisco como comodín para poder hacer referencia a todas las clase ubicadas dentro del paquete mediotransporte: import mediotransporte.*; Con ésta instrucción no importa el contenido de los paquetes interiores a mediotransporte, (lo que quiere decir que si la clase Coche está dentro del paquete mediotransporte motor, no sería importada con esa instrucción, ya que el paquete motor no ha sido importado, sí lo sería la clase mediotransporte.BarcoDeVela). Por ello en el ejemplo lo completo sería import mediotransporte.*; import mediotransporte.Motor.*
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Cuando desde un programa se hace referencia a una determinada clase se busca ésta en el paquete en el que está colocada la clase y, sino se encuentra, en los paquetes que se han importado al programa. Si ese nombre de clase se ha definido en un solo paquete, se usa. Si no es así podría haber ambigüedad por ello se debe usar un prefijo delante de la clase con el nombre del paquete. Las clases son visibles en el mismo paquete a no ser que se las haya declarado con el modificador private. Para que una clase pertenezca a un determinado paquete, debemos incluir antes de la clase la palabra reservada package. package nombrepaquete; public class MiClase { //CODIGO DE LA CLASE } Para poder compilar un paquete será necesario crearnos un subdirectorio dentro del sistema de ficheros con el mismo nombre de paquete que hayamos pensado. Los paquetes se suelen escribir todos en minúscula y las clases en Mayúscula, es una buena práctica hacerlo asi para mantener la coherencia del lenguaje de Java. Veamos un ejemplo rápido: package paqueteprueba; public class PruebaPaquete { public static void main(String[] args) { System.out.println("Estoy en el paqueteprueba"); } } Nos hemos creado una clase en el paquete denominado paqueteprueba. directorio llamado igual en nuestro sistema de ficheros.
Debemos crearnos un
Ahora para compilar, debemos situarnos en el directorio inmediatamente anterior (PracticasJava) y ejecutar la siguiente sentencia: javac paqueteprueba\PruebaPaquete.java Se creará la clase con el paquete ya incluido:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Ahora se nos ha generado el fichero class dentro del directorio paqueteprueba, solamente nos quedaría ejecutar la instrucción para visualizar la aplicación ya compilada. Para ello, debemos escribir el nombre del paquete seguido del nombre de la clase. java paqueteprueba.PruebaPaquete Y como vemos, el resultado es la clase compilada dentro de un paquete:
Modificadores de ámbito Los modificadores de ámbito especifican la forma en que puede accederse a los mismos objetos desde otras clases. Estos modificadores de ámbito son:
private public protected sin especificar modificador
El modificador de ámbito por defecto quiere decir que se declara la variable o método sin indicar su visibilidad para otros objetos.
Modificador private El modificador de ámbito private es el más restrictivo de todos. Todo elemento declarado como private, ya sea una clase, un método o una propiedad es visible únicamente dentro del ámbito dónde se declara. No existe ninguna forma de acceder al mismo si no es a través de algún método (no private) que devuelva o modifique su valor. Una buena metodología de diseño de clases es declarar los atributos private siempre que sea posible, ya que esto evita que algún objeto pueda modificar su valor si no es a través de alguno de sus métodos diseñados para ello. Asi es como se crean lo que se llaman métodos setter y getter. En realidad es cómo funcionan los métodos en java. Se accede a las variables miembros de la clase mediante métodos get y set que se llaman igual que el miembro de la clase.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Ésta técnica permite también controlar el acceso que se realiza sobre el valor de un miembro de la clase y realizar acciones en el caso de que no nos guste el valor que se va a establecer para el miembro. Vamos a visualizar un ejemplo de las ventajas de utilizar acceso a las variables miembro a partir de métodos get y set. Nos vamos a crear una clase Empleado: public class Empleado { public String Nombre; public String Apellidos; public String NIF; public int Salario; public Empleado() { this.Nombre = ""; this.Apellidos = ""; this.NIF = ""; this.Salario = 0; } } A continuación vamos a utilizar la clase Empleado para introducir valores en sus miembros: public class PruebaEncapsulacion { public static void main(String[] args) { Empleado emp = new Empleado(); emp.Nombre = "Jose Maria"; emp.Apellidos = "Gutierrez Hernandez"; emp.NIF = "14141238G"; emp.Salario = -2000; System.out.println("Nombre Empleado: " + emp.Nombre); System.out.println("Apellidos Empleado: " + emp.Apellidos); System.out.println("NIF Empleado: " + emp.NIF); System.out.println("Salario Empleado: " + emp.Salario); } } El resultado lo podemos comprobar cuando compilemos y ejecutemos la clase:
Todo está correcto y funciona perfectamente. ¿Que sucede por ejemplo con el Salario?. Podemos perfectamente dejarlo como está o podríamos poner una condición. En nuestro ejemplo el salario es www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
negativo, pero puestos a pensar en la lógica de la aplicación, un salario nunca podría estar en negativo, al igual que el NIF debería de tener una coherencia y “controlar” que todo está correcto, número de elementos o que la letra se corresponda. Si nos planteamos el punto de vista de control de acceso a los miembros, no podemos hacer nada tal y como tenemos planteada la aplicación, ya que el acceso a la variable NIF o salario es inmediato a través de la clase Empleado. En ese caso es dónde nacen los métodos get y set. En realidad lo que se realiza es lo siguiente. Los miembros de la clase son privados, mientras que los métodos de acceso son públicos, de forma que podemos controlar los valores que el usuario nos proporciona desde el método y decidir que hacer en el caso que no nos gusten los valores adecuados para nuestro miembro. El método set establece el valor para el miembro y debe ser un método de acción, por lo que lo declararemos como void. El método get devuelve el valor del miembro, por lo que debe devolver el mismo tipo de dato que el miembro que está manejando. La sintaxis sería la siguiente: private String Miembro; public String getMiembro() { //Devolvemos el valor del miembro return this.Miembro; } public void setMiembro(String valor) { //Asignamos el valor del miembro this.Miembro = valor;; } Veamos el ejemplo tal y cómo sería correcto implementando la encapsulación: public class Empleado { private String Nombre; private String Apellidos; private String NIF; private int Salario; public Empleado() { this.Nombre = ""; this.Apellidos = ""; this.NIF = ""; this.Salario = 0; } public String getNombre() { return this.Nombre; } public void setNombre(String nom) { this.Nombre = nom; } public String getApellidos() www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
{ return this.Apellidos; } public void setApellidos(String ape) { this.Apellidos = ape; } public String getNIF() { return this.NIF; } public void setNIF(String nif) { this.NIF = nif; } public int getSalario() { return this.Salario; } public void setSalario(int sal) { if (sal > 0) { this.Salario = sal; }else{ this.Salario = 800; } } } Ahora podemos utilizar de nuevo la clase Empleado, pero solamente nos está ofreciendo acceso desde los métodos set y get: public class PruebaEncapsulacion { public static void main(String[] args) { Empleado emp = new Empleado(); emp.setNombre("Jose Maria"); emp.setApellidos("Gutierrez Hernandez"); emp.setNIF("14141238G"); emp.setSalario(-2000); System.out.println("Nombre Empleado: " + emp.getNombre()); System.out.println("Apellidos Empleado: " + emp.getApellidos()); System.out.println("NIF Empleado: " + emp.getNIF()); System.out.println("Salario Empleado: " + emp.getSalario()); } } Como podemos comprobar en la imagen, un Empleado nunca podrá tener un Salario menor a cero, si se diese el caso (como en el ejemplo -2000), automáticamente, le cambiamos el valor del Salario www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
a 800. Esto es un control de acceso a los miembros de la clase y es uno de los elementos más importantes dentro de la encapsulación.
Modificador public El modificador de acceso public es el menos restrictivo de todos. Un atributo public será visible en cualquier clase, propiedad o método que desee acceder a él, simplemente anteponiendo el nombre de la clase. Las aplicaciones bien diseñadas minimizan el uso del modificador de acceso public y maximizan el uso del modificador private. La forma apropiada de acceder y modificar propiedades o métodos es a través de propiedades privadas y métodos public como ya hemos visto, de forma que se accede a una propiedad a través de métodos que accedan a los mismos, aunque en ocasiones, para acelerar el proceso de programación, se declaran de tipo public y se modifican sus valores desde otras clases, pero esto no es una buena praxis.
Modificador protected Los atributosprotected pueden ser accedidos por las clases del mismo paquete (package) y por las subclases del mismo paquete, pero no pueden ser accedidos por subclases de otro paquete, aunque sí pueden ser accedidas las variables protected. Es muy sencillo, los miembros declarados como protected son accesibles desde las clases del mismo paquete. Si nos situamos en otro paquete, solamente accederán los miembros que hereden directamente de la clase en cuestión. Son miembros “protegidos” y es un modificador que sirve básicamente para la herencia. Vamos a visualizarlo en un sencillo ejemplo práctico. Nos vamos a crear la clase Empleado. Nos vamos a declarar una variable protected a la que llamaremos SalarioMinimo. La clase empleado irá en el paquete llamado personasempresa. Lo que haremos en la clase Empleado será controlar que el usuario no pueda igualar un salario inferior al salario minimo del empleado, en éste caso a 600. package personasempresa; public class Empleado { private String Nombre; private int Salario; protected int SalarioMinimo; public Empleado() { this.Nombre = ""; this.Salario = 0; this.SalarioMinimo = 600; } public String getNombre() { www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
return this.Nombre; } public void setNombre(String nom) { this.Nombre = nom; } public int getSalario() { return this.Salario; } public void setSalario(int sal) { if (sal > 0) { this.Salario = sal; }else if (sal < this.SalarioMinimo) { this.Salario = this.SalarioMinimo; } } } Ahora compilaremos la clase empleado y no deberíamos tener ningún error. Debemos recordar que tenemos que crearnos una carpeta con el mismo nombre del paquete y compilar la clase dentro de dicha carpeta. Una vez compilada la clase, lo que haremos será crearnos otra clase que utilizará el paquete y la clase empleado para intentar modificar el SalarioMinimo del empleado. import personasempresa.*; public class PruebaEncapsulacion { public static void main(String args[]) { Empleado emp = new Empleado(); emp.SalarioMinimo = 200; System.out.println("El salario minimo del empleado es: " + emp.SalarioMinimo); } }
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Como podemos comprobar, el acceso al miembro SalarioMinimo nos indica que está protegido, por lo que no podemos acceder a dicho miembro. Para saber si podemos obtener acceso tenemos que hacernos una pregunta que nos resolverá muchas dudas de acceso a un miembro. ¿La clase PruebaEncapsulacion es un Empleado? La respuesta es NO. La clase PruebaEncapsulacion utiliza un empleado. Ahora lo que vamos a hacer será crearnos una clase llamada Ejecutivo que heredará de la clase Empleado, y veremos que aunque no se encuentre en el mismo paquete podrá acceder al miembro SalarioMinimo. import personasempresa.*; public class Ejecutivo extends Empleado { public Ejecutivo() { this.SalarioMinimo = 1250; } } Compilamos la clase y veremos que no existe ningún error, por lo que nos permite el acceso al miembro protegido SalarioMinimo. Ahora si podemos plantearnos la pregunta de nuevo: ¿La clase Ejecutivo es un Empleado? La respuesta es SI. La clase Ejecutivo es un empleado y, por lo tanto, puede utilizar el miembro SalarioMinimo.
Modificador por defecto de los atributos Los atributos que no llevan ningún modificador de ámbito pueden ser accedidos desde las clases del mismo paquete, pero no desde otros paquetes. Éste cuadro representa un resumen de los diferentes modificadores que existen: MODIFICADOR public private protected Por defecto
MISMA CLASE SI SI SI SI
HERENCIA SI NO SI NO
PAQUETE SI NO SI SI
TODOS SI NO NO NO
Ver Video: Paquetes getter y setter, en la Unidad 9, en el Módulo 1, en la plataforma elearning Laboratorio: Creación y uso de paquetes. Objetivo Conocer el funcionamiento de los paquetes en Java y su utilización.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Enunciado Vamos a realizar un laboratorio en el que conoceremos el uso de los paquetes y cómo podemos implementarlos para utilizarlos con otras clases. El concepto de éste ejemplo tiene más que ver con las acciones y la creación de los productos compilados que con la propia creación y la lógica de las clases.
Solución: Comenzaremos creándonos una clase inicial package laboratoriopaquetes; public class ClasePaquete1 { protected int variableprotegida = 20; public int variablepublica = 30; private int variableprivada = 40; } En el momento de almacenar la clase, debemos crearnos una carpeta con el nombre del mismo paquete que estamos almacenando y guardarla dentro. En nuestro ejemplo, crearemos una carpeta con el nombre laboratoriopaquetes dentro de la carpeta PracticasJava y llamaremos a nuestro fichero ClasePaquete1.
Nos crearemos otra clase y la situaremos al mismo nivel que la anterior, es decir, dentro del directorio y paquete laboratoriopaquetes. package laboratoriopaquetes; public class ClasePaquete2 { public int variablepublica = 14; } A continuación vamos a crearnos otro paquete más interno, de forma que vamos a crear una estructura en la que situaremos a otro nivel más otra clase dentro de un paquete. Llamaremos al paquete otropaquete y a la clase ClasePaquete3. package laboratoriopaquetes.otropaquete; public class ClasePaquete3 { public int variablepublica = 25; } Almacenaremos la nueva clase dentro del directorio laboratoriopaquetes, creándonos una carpeta con el nombre del nuevo paquete otropaquete:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Debemos tener la siguiente estructura de ficheros:
Ahora que tenemos una estructura más o menos compleja de los elementos que deseamos crear, debemos utilizar los paquetes creados para visualizar el correcto funcionamiento. Nos crearemos una clase dentro del directorio PracticasJava que utilizará las clases contenidas dentro de los paquetes creados: import laboratoriopaquetes.*; public class UsoPaquetes { public static void main(String[] args) { ClasePaquete1 c1 = new ClasePaquete1(); ClasePaquete2 c2 = new ClasePaquete2(); ClasePaquete3 c3 = new ClasePaquete3(); System.out.println("Uso de Paquetes en Java"); } } Al utilizar la instrucción import, estamos accediendo a todos los objetos que están dentro del nivel de la primera carpeta, por lo que podemos acceder a la clase Paquete1 y Paquete2.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Si visualizamos el error, podemos comprobar que nos está dando una excepción cuando utilizamos la clase Paquete3. Esto sucede porque el hecho de acceder a un nivel de paquetes, no implica que accedamos al siguiente nivel. Dicho de otra forma, el hecho de que nos posicionemos dentro de la carpeta laboratoriopaquetes no implica que veamos los archivos que existen dentro de la carpeta otropaquete. Si deseamos visualizar los ficheros de la carpeta otropaquete debemos “entrar” en ella, por lo que debemos acceder mediante la instrucción import a dicho paquete también si deseamos utilizar las clases contenidas dentro: import laboratoriopaquetes.*; import laboratoriopaquetes.otropaquete.*; public class UsoPaquetes { public static void main(String[] args) { ClasePaquete1 c1 = new ClasePaquete1(); ClasePaquete2 c2 = new ClasePaquete2(); ClasePaquete3 c3 = new ClasePaquete3(); System.out.println("Uso de Paquetes en Java"); } } Si compilamos con el nuevo código y el import adecuado, veremos que todo compila y funciona correctamente, ya que hemos ido siguiendo todos los pasos y accediendo a las diferentes estructuras (niveles) para visualizar las clases y utilizarlas:
Actividades “Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades que encontrará en la unidad correspondiente de la plataforma eLearning”. www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 10. Creando y usando arreglos Introducción En múltiples ocasiones dentro de una aplicación necesitamos almacenar mucha información de un mismo tipo, como por ejemplo, todos los precios de una tienda o todas las notas de una clase. Para almacenar ésta información están los arreglos, llamados arrays. Un array permite almacenar información de muchos elementos en un solo objeto, pudiendo acceder a dichos elementos mediante un índice. Además del concepto de array, veremos en éste capítulo el concepto de colección. Una colección es igual que un array, un conjunto de elementos a los que se accede por un índice, la diferencia está en que un array contiene un número de elementos fijo, mientras que una colección puede contener más elementos y su capacidad cambia a medida que se agregan elementos a ese conjunto.
Objetivos
Aprender el manejo de arrays unidimensionales y bidimensionales.
Conocer el concepto de colección.
Diferenciar entre arrays y colecciones y aprender cuando utilizar un objeto o manejar otro objeto.
Concepto de Array Los arreglos son varios objetos en uno, pero que se accede a cada uno de los objetos almacenados por medio de un índice. Son un conjunto de elementos accesibles desde un único objeto a partir de una posición específica. Las Matrices o arrays multidimensionales.
(llamados
también
arreglos)
pueden
ser
unidimensionales
o
Los arreglos son estáticos, lo que quiere decir que no podemos redimensionar un array. Si quisiéramos redimiensionar un array sería destruido todo su contenido, perdiendo la información que tuviéramos almanenada en su interior. Los elementos que pondremos en nuestro arreglo de datos deben estar definidos en cantidad, no en valor. Los arreglos tienen una cantidad de elementos específica, todos comienzan en cero y su límite superior será el número de elementos totales menos 1. Los Arrays tienen una propiedad para averiguar el número de elementos que contiene en su interior. Es la propiedad length. Esta variable nos devuelve el número de elementos que posee el array. Hay que tener en cuenta que es una variable de solo lectura, es por ello que no podremos realizar una asignación a dicha variable. Tenemos que tener claro el atributo length nos devuelve el número de posiciones o huecos que existen en el interior del array, el hecho que hayamos declarado un array con una capacidad determinada, no indica que el contenido del array esté creado, podremos comprobarlo a lo largo del módulo. Simplemente esto quiere decir que un array puede tener posiciones con “contenido” y posiciones con valores por defecto en el caso de que sean tipos primitivos y valores nulos en el caso de que sean objetos referenciados.
Arrays Unidimensionales www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Son el concepto que acabamos de explicar ahora mismo, un objeto compuesto por múltiples elementos, dónde cada uno de los elementos tiene una posición en el conjunto. En Java un arreglo se representa por un objeto que tiene un límite de elementos al ser definido, o en alguna parte de nuestro programa le asignaremos un objeto arreglo de cierto tipo. Por ejemplo, imaginemos que deseamos almacenar una lista de 6 textos, deberíamos de crearnos un array de 6 elementos, dónde el primer texto estaría en la posición cero y el último texto estaría en la posición 5. Podemos visualizarlo en éste ejemplo gráfico: POSICION 0 1 2 3 4 5
TEXTO ALMACENADO En Un Lugar De La Mancha
De forma que si queremos acceder a alguna posición del array para acceder a algún elemento en concreto deberíamos escribir: Nombrearray[posición]; En nuestro ejemplo concreto, si nuestro array se llamase textos: Textos[2] Devolvería el valor de “Lugar”. Un array puede ser creado para que contenga cualquier tipo de dato, ya sea un conjunto de elementos de tipos primitivos (int, double, string…), o un conjunto de objetos referenciados (objetos de clases existentes o creadas por el propio programador). La sintaxis para crear un array e indicar al compilador que es un arreglo se realiza mediante corchetes, dónde en la creación del objeto es dónde indicaríamos el número de elementos a contener dentro del array. Para declarar una array unidimensional se puede realizar de varias formas:
Creando el array sin contenido:
int numeros[] = new int[5]; Creando un array, e inicializando el número de elementos posteriormente en el código. int numeros[]; int numeroelementos = 5; numeros = new int[numeroelementos]; Creando un array con contenido e inicializando los valores que deseamos que contenga en su interior. Dos tipos de sintaxis: int numeros[] = new int[] {2,5,6,7,8}; int numeros[] = {2,5,6,7,8}; En las dos primeras opciones, los elementos internos del array son inicializados a su valor “vacío” o “null”. A diferencia de los objetos simples, cuando utilizamos arrays, los objetos de su interior son inicializados y el compilador nos permite trabajar y ejecutar la aplicación. Para inicializar los valores de un array, también podemos hacer lo posteriormente por código, igualando el nombre del array y de la posición que deseamos modificar por el valor que necesitamos almacenar. Nombrearray[posición] = valor; Llevado a código sería la siguiente instrucción: www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
int numeros[] = new int[]; numeros[0] = 2; numeros[1] = 5; numeros[2] = 6; numeros[3] = 7; numeros[4] = 8; Veamos la diferencia entre una variable simple y un conjunto de variables simples (array): Si escribimos el siguiente código en una clase, declarándonos una variable única del tipo int, veremos que el compilador nos muestra una excepción al querer compilar la clase: public class PruebaArreglos { public static void main(String args[]) { int numero; System.out.println("El valor del numero es "+numero); } }
Vemos que como resultado, el programa de Java, impide al compilador utilizar variables que no hayan sido inicializadas con un valor como hemos visto en temas anteriores. Si ahora en cambio nos declaramos un array del mismo tipo, veremos que el resultado es totalmente distinto, permitiéndonos compilar sin ningún tipo de excepción: public class PruebaArreglos { public static void main(String args[]) { int arraynumeros[] = new int[5]; System.out.println("El valor del numero es "+arraynumeros[2]); } }
El compilador nos permite generar el archivo class sin ningún problema, si ahora ejecutásemos el código para visualizar la lógica de la clase veremos lo siguiente:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Lo que sucede es que el array al ser declarado como un tipo de datos primitivos (en nuestro ejemplo int), los valores de los objetos internos se inicializan a un valor inicial, en éste ejemplo en concreto al número cero. Ahora vamos a visualizar que sucedería en el caso de trabajar con objetos referenciados. Nos vamos a crear la siguiente clase, para posteriormente, crearnos un array con objetos de dicha clase y acceder a sus atributos. public class MiClasePrueba { public int num; public String texto; public MiClasePrueba() { num = 19; texto = "clase de prueba para arrays"; } } Ahora vamos a utilizar el nuevo objeto creado, pero en un array. Primero declararemos una variable simple para manejar un único objeto referenciado y a continuación un conjunto de objetos en un array. public class PruebaArreglos { public static void main(String args[]) { MiClasePrueba objetosimple = new MiClasePrueba(); System.out.println("Valor del Objeto Simple: "+objetosimple.texto); MiClasePrueba objetos[] = new MiClasePrueba[5]; System.out.println("Valor del Objeto Compuesto "+objetos[2].texto); } }
Como podemos comprobar, el mensaje del objeto simple es visualizado después de compilar la clase, pero al llegar a “utilizar” el objeto compuesto nos ofrece una excepción de la clase NullPointerException, lo que quiere decir al final de todo es que estamos creando un conjunto de elementos, pero dichos elementos no han sido creados en el interior del array, debemos hacer un new sobre algún objeto del array que deseamos crear.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
El compilador no detecta ésta excepción, ya que no verifica el interior del contenido del objeto array, sino que solamente detecta la creación del conjunto por si ha sido creado correctamente e inicializados sus valores para que sean utilizados. La solución de la excepción sería creando un objeto en la posición que deseamos utilizar: public class PruebaArreglos { public static void main(String args[]) { MiClasePrueba objetosimple = new MiClasePrueba(); System.out.println("Valor del Objeto Simple: "+objetosimple.texto); MiClasePrueba objetos[] = new MiClasePrueba[5]; objetos[2] = new MiClasePrueba(); System.out.println("Valor del Objeto Compuesto "+objetos[2].texto); } } De forma que el valor resultante después de la compilación sería totalmente diferente y accederíamos al objeto creado:
Arrays Multidimensionales Debemos pensar en ellos como una tabla, nos permiten almacenar más de un índice por cada elemento. Para entender mejor el concepto, pensemos en un conjunto de personas, cada persona contiene como dato un nombre y un dni. Son dos valores a almacenar, por un lado el nombre de la persona y por otro el dni. En lugar de crearnos dos arrays, se utiliza un array único con dos dimensiones o posiciones, pudiendo acceder a cada elemento por su posición en el conjunto y el dato en cuestión. Para visualizarlo mejor, podemos visualizar la siguiente tabla: Imaginemos un array compuesto por nombres llamado datos. FILAS 0 1 2
0 NOMBRE Nacho Llanos Andrea Serrano Lucia Gutierrez
1 DNI 12345678N 23451235H 98765432P
COLUMNAS
Según nuestro cuadro, tenemos dos datos almacenados en cada una de las filas, de forma que accederíamos a ellos mediante posición de fila y posteriormente, posición de columna. nombrearray[POSICION FILA] [POSICION COLUMNA] De forma que si deseásemos saber el DNI de Lucía Gutierrez escribiriamos: datos [2] [1]
98765432P
Para crearnos arrays multidimensionales sucede lo mismo que con arrays unidimensionales, existen múltiples formas dependiendo de lo que deseemos realizar o almacenar sobre el array:
Declaración y creación de un array multidimensional sin contenido:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
int[][] arraymultidimensional = new int[2][3]; Estamos creando un array que contendría dos filas y tres columnas para cada fila.
Declarar un array multidimensional y crearlo posteriormente en el código de la aplicación: int[][] arraymultidimensional; int numerofilas = 2; int numerocolumnas = 3; arraymultidimensional = new int[numerofilas][numerocolumnas];
Declarar y crear un array multidimensional con elementos en su interior, asignados en la creación del objeto:
String [ ][ ] datos = { { "Nacho Llanos", "12345678N" } ,_ { "Andrea Serrano" , "23451235H" } , { "Lucia Gutierrez" , "98765432P" } };
Declarar un array multidimensional y asignar los valores posteriormente:
String [ ][ ] arraymultidimensional = new String[2][2]; arraymultidimensional[0][0] = "Nacho Llanos"; arraymultidimensional[0][1] = "12345678N"; arraymultidimensional[1][0] = "Andrea Serrano"; arraymultidimensional[1][1] = "23451235H"; Vamos a ver un ejemplo para crearnos un recorrido sobre un array multidimensional que contenga datos en su interior y cómo podemos recuperarlos para mostrarlos todos por pantalla: public class PruebaArreglos { public static void main(String args[]) { String [ ][ ] arraymultidimensional = new String[3][2]; arraymultidimensional[0][0] = "Nacho Llanos"; arraymultidimensional[0][1] = "12345678N"; arraymultidimensional[1][0] = "Andrea Serrano"; arraymultidimensional[1][1] = "23451235H"; arraymultidimensional[2][0] = "Lucia Gutierrez"; arraymultidimensional[2][1] = "98765432P"; //Recorrido por el array multidimensional for (int i = 0; i < arraymultidimensional.length; i++) { //Recorremos las filas for (int z = 0; z < arraymultidimensional[i].length; z++) { //Recorremos las columnas System.out.println("El dato en la fila " + i + ", _ columna " + z + " es: " + arraymultidimensional[i][z]); } } } } Como resultado veremos que hemos recorrido las dos dimensiones del array.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Para averiguar la longitud de las filas, bastaría con utilizar la propiedad length sobre el objeto array: arraymultidimensional.length Si deseamos saber la longitud de las columnas de una fila, debemos aplicar el atributo length sobre la fila en cuestión y contar el número de columnas existentes para esa fila: arraymultidimensional[numerofila].length
Arrays de Caracteres Los conjuntos de caracteres en Java son objetos de la clase String. La clase String contiene en su interior un conjunto de elementos separados entre sí cada uno de ellos por la clasechar, lo que quiere decir que cada objeto String es un conjunto de elementos de la clase char. A la inversa sucede exactamente lo mismo, un array de la clase char es “convertido” a un objeto de la clase String que se puede representar graficámente como un conjunto de caracteres en un nuevo objeto String. Para comprobar éste concepto bastaría con declararnos un array de la clase char e incluir en su interior una serie de caracteres en cada posición. public class PruebaArreglos { public static void main(String args[]) { char[] letras = {'a', 'e', 'i', 'o', 'u'}; String texto = new String(letras); System.out.println(letras); System.out.println(texto); System.out.println("Un elemento del conjunto CHAR: " + letras[1]); System.out.println("Un elemento del conjunto STRING: " + texto.charAt(2)); } }
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Debido a ello, podemos acceder a un único elemento char en la clase String, al igual que podemos acceder a un elemento dentro del array char. También podemos iniciar una array de tipos char con elementos enteros, debido a que cada carácter tiene asociado un entero Unicode desde 0 a 65535. Recordando que los primeros 255 caracteres pertenecen al código ASCII. char[] letras = {100, 105, 125, 157, 89}; Lo que daría como resultado: di}?Y Vamos a crearnos un programa en el que almacenaremos todos los caracteres ASCII dentro de un array de la clase char, para posteriormente mostrarlos por pantalla en la clase String o uno a uno recorriendo cada uno de los caracteres. import java.io.*; public class PruebaArreglos { static char[] caracteres = new char[255]; public static void main(String args[]) throws IOException { System.out.println("Almacenando caracteres ASCII..."); BufferedReader lector=new BufferedReader(new InputStreamReader(System.in)); int opcion = 0; int posicion = 0; String datoteclado; for (int i = 0; i < caracteres.length; i++) { caracteres[i] = (char)i; } System.out.println("Elementos almacenados..."); do { System.out.println("1.- Mostrar todos los caracteres"); System.out.println("2.- Seleccionar una posicion del ASCII"); System.out.println("3.- Salir"); System.out.println("Seleccione una opcion:"); datoteclado= lector.readLine(); opcion = Integer.parseInt(datoteclado); switch (opcion) { case 1: System.out.println(caracteres); break; case 2: System.out.println("Introduzca una posicion:"); datoteclado= lector.readLine(); posicion = Integer.parseInt(datoteclado); String letra = seleccionarLetra(posicion); System.out.println("La letra ASCII de " + posicion + " es " + letra); } }while(opcion != 3); System.out.println("Fin del programa"); } public static String seleccionarLetra(int posicion) www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
{ String letra = String.valueOf(caracteres[posicion]); return letra; }
}
Cómo podemos comprobar, el resultado de la ejecución del programa nos permite acceder a cada uno de los elementos del array mediante el objeto caracteres o acceder a todos los elementos mediante un String creado en la instrucción System.out.println(caracteres).
Colecciones Cuando las características de un array se quedan incompletas para la lógica del programador es cuando se usan colecciones. Las colecciones son objetos que contienen un conjunto de objetos a su vez, exactamente igual que un array, además se accede a cada uno de los elementos mediante un índice para recuperar cada uno de los elementos. La diferencia entre un array una colección es simple. Un array es un objeto con una longitud de elementos estáticos. Es decir, un array al ser creado se le debe especificar el número de elementos que va a contener en su interior, y dicho número de elementos no pueden ser modificado. Además, un array puede contener objetos nulos en su interior y no devolver el número “real” de elementos que existen en su interior, sino solamente su capacidad, es decir, puede contener huecos en algunas posiciones y datos en otras. Una colección es un objeto con un conjunto de elementos dinámico. El número de elementos de la colección puede crecer y decrecer. Una colección se dimensiona al número de elementos reales que contiene. No puede contener huecos nulos en su interior a no ser que el programador lo haya especificado mediante código. Son objetos creados para una lógica en la que el programador no sabe el número de elementos que va a tener que almacenar. Además, una colección siempre devolverá el número de elementos que contiene, no la capacidad de elementos que puede almacenar en su interior. La librería para trabajar con colecciones está ubicada en el paquete java.util. Los objetos que podemos almacenar en una colección son los mismo que en un array, desde tipos primitivos hasta objetos referenciados.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
La gran desventaja en el uso de colecciones de Java es la pérdida de la identidad del tipo de datos almacenados cuando se coloca un objeto en su colección. Teniendo en cuenta querer hacer un conjunto de elementos lo más general posible, se hizo de forma que se manejase directamente objetos de la clase object, independientemente del la clase o tipo de objeto almacenado en su interior. Con la versión de Java 1.5, éste problema se solucionó. Se implementaron colecciones de forma que se pueden declarar objetos de una determinada clase y solamente se pueden almacenar objetos de dicha clase. La gran ventaja es que no tenemos que realizar casting para recuperar cualquier objeto, sino que la referencia al objeto ya está escrita en la propia declaración de la colección. La desventaja radica en que no podemos almacenar cualquier clase de objeto, solamente del mismo tipo, pero para ello existen multiples clases de colecciones que nos pueden solucionar un problema lógico en concreto. Podemos diferenciar las colecciones en dos grandes familias:
Colección (Collection): Son un grupo de elementos individuales. Es lo más parecido que existe a un array unidimensional.
Mapa (Map): Es un grupo de parejas de elementos, como un array bidimensional. Podriamos realizar la misma acción con una colección de parejas, pero el modo de tratarlas dependería de la sincronización que tuviésemos a la hora de almacenar los datos en cada índice para que coincidieran.
Las colecciones y los mapas pueden ser implementados de muy diversas manera, en función de las necesidades de la programación. Dentro de éstas dos familias que acabamos de nombrar, existen tres tipos de colecciones: Map, List y Set, y solamente dos o tres implementaciones de cada una de ellas, por lo que podemos afirmar que aprender el manejo de una colección implica saber el resto de colecciones. Es parecido al mundo real, con saber conducir un coche, podemos conducir cualquier tipo de coche, independientemente del tipo, ya que las características básicas son las mismas para todos. Todas las colecciones pueden producir un objeto Iterator invocando al método Iterator(). Un Iterator es un enumerador que permite recorrer cada uno de los elementos que existen dentro de la colección hasta llegar al último. Vamos a visualizar los métodos más importantes dentro de las colecciones Set o List: add(object): Incluye un nuevo elemento dentro de la colección. addAll(Collection): Inserta todos los elementos que se pasan desde otra colección a la colección que realiza la llamada. clear(): Elimina todos los elementos de la colección, dejando el número de elementos a cero. contains(object): Devuelve un boolean indicando si el objeto que se pasa como argumento existe dentro de la colección. isEmpty(): Devuelve un boolean indicando si la colección tiene algún elemento ya incluido o no. iterator(): Devulve un Iterator que se utiliza para recorrer todos los elementos dentro de la colección uno a uno. remove(object): Elimina un objeto de la colección, pasando como argumento el propio objeto a eliminar. removeAll(Collection): Elimina todos los elementos que están dentro de la colección que se envía como argumento. size(): Devuelve el número de elementos que existen dentro de la colección. Debemos de recordar que siempre una colección va a devolver el número total de elementos que contiene.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
toArray(): Convierte la colección en un array y devuelve todos los elementos para poder ser incluidos en ella.
Colección Set Cualquier clase denominada Set implementa la interfaz Set de colecciones. Las colecciones Set no permiten contener duplicados en su interior y lo que es más importante, se ordenan internamente a través de SortedSet. La forma de ordenarlos es de forma ascendente. Incluye diversos métodos para acceder a sus elementos, además de iterator para recorrer el conjunto de sus elementos. Los atributos más importantes (además de los típicos de todas las colecciones) son: first(): Devuelve el primer elemento dentro de la colección. last(): Devuelve el último elemento de la colección. Vamos a visualizar un ejemplo para comprobar la utilidad y la facilidad de las colecciones Set. Nos crearemos un objeto TreeSet que herada de la interfaz Set y comprobaremos todas las características. La lógica del problema será una clase que generará 10 números aleatorios comprendidos entre 0 y 10. import java.util.*; public class PruebaColecciones { public static void main(String args[]) { Random rnd = new Random(); TreeSet numerosordenados = new TreeSet(); for (int i = 0; i < 10; i++) { int numeroaleatorio = (int)(rnd.nextDouble() * 10); numerosordenados.add(numeroaleatorio); } Iterator item = numerosordenados.iterator(); while (item.hasNext()) { System.out.println(item.next()); } } } Como resultado veremos todos los elementos introducidos dentro de la colección:
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Si ejecutamos varias veces, veremos que el número de elementos dentro de la colección variará en cada ejecución. Esto se debe a que la colección no permite elementos repetidos, por lo que cada vez que se repite un número en la secuencia entre 0 y 10, lo elimina directamente de la colección. Si aumentamos el número de valores aleatorios (por ejemplo de 0 a 100), comprobaremos que la colección se llena al completo y que los números son ordenados automáticamente. for (int i = 0; i < 10; i++) { int numeroaleatorio = (int)(rnd.nextDouble() * 100); numerosordenados.add(numeroaleatorio); }
Como podemos comprobar, al aumentar el número de posibilidades de que no se repitan números dentro de la colección, se llena al completo (10 elementos) y se ordenan internamente dichos elementos. Existe una sintaxis nueva para recorrer los elementos dentro de una colección, sin necesidad de declararnos un objeto de la clase Iterator. Esto nos permite más claridad de código, pero nos impide realizar acciones sobre el objeto que estamos recorriendo. La sintaxis es la siguiente: for(Object elemento : COLECCION) { //ACCIONES SOBRE CADA ELEMENTO } Podemos visualizar la sintaxis dentro del anterior ejemplo: import java.util.*; public class PruebaColecciones { public static void main(String args[]) { Random rnd = new Random(); TreeSet numerosordenados = new TreeSet(); for (int i = 0; i < 10; i++) { int numeroaleatorio = (int)(rnd.nextDouble() * 100); numerosordenados.add(numeroaleatorio); } for(Object numero : numerosordenados) www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
{ System.out.println(numero); } System.out.println("Primer numero Coleccion: " + numerosordenados.first()); System.out.println("Ultimo numero Coleccion: " + numerosordenados.last()); System.out.println("Elementos en la coleccion: " + numerosordenados.size()); } }
Colección List Es una colección de objetos que implementa la Interfaz List. Dentro de la implementación de ésta colección tenemos dos clases que son las más importantes para éste tipo:
Vector: Colección que permite duplicados. Permite la referencia del objeto que vamos a incluir en su interior. ArrayList: Colección que permite duplicados. Sólo se almacenan elementos object dentro de su interior, por lo que tenemos que realizar Casting entre objetos para recuperar sus elementos.
LinkedList: Colección en la que cada elemento tiene una referencia al anterior y posterior elemento. La diferencia que tiene una lista con un Set es que la lista mantiene un orden arbitrario de los elementos y permite acceder a los elementos por dicho orden. Podríamos decir que en una lista, el orden es el dato. Es decir, el orden es información importante que la lista también nos está almacenando. Dicho en otras palabras, el orden de una lista se establece por cada elemento que hemos introducido, no se reordena, cada elemento que pongamos en su interior irá el último. A diferencia de un Set, una lista permite acceder a un número específico de elemento. En un Set no existe porque ni siquiera estamos seguros de que si volvemos a recorrer la colección los elementos aparecerán en el mismo orden. Una lista sí debe permitir acceder al tercer elemento, por eso se añaden los siguientes métodos: get(int posicion) Obtiene el elemento en la posición pasada como parámetro. set(int posicion, v valor) Pone al elemento v en la posición enviada como parámetro. Existen en Java principalmente dos implementaciones de List, las dos útiles en distintos casos. Una de ellas es casi igual a los arreglos unidimensionales. Esta implementación es ArrayList. La ventaja de ArrayList por sobre un array común es que es expansible, es decir que crece a medida que se le añaden elementos (mientras que el tamaño de un array es fijo desde su creación). Lo bueno es que el tiempo de acceso a un elemento en particular es mínimo. Lo malo es que si queremos eliminar un elemento del principio, o del medio, la clase debe mover todos los que le siguen a la posición anterior, para “quitar” el agujero que deja el elemento removido y que no existan huecos en el interior de la colección. Esto hace que quitar elementos del medio o del principio sea costoso. Otra implementación es LinkedList (lista enlazada). En ésta, los elementos son mantenidos en una serie de nodos atados entre sí como eslabones de una cadena. Cada uno de estos nodos apunta a su antecesor y al elemento que le sigue. Nada más. No hay nada en cada uno de esos nodos que tenga algo que ver con la posición en la lista. Para obtener el elemento número “n”, esta implementación de List necesita entonces empezar desde el comienzo, desde el primer nodo, e ir avanzando al “siguiente” n veces. Buscar el elemento 400 entonces implica 400 de esos pasos. La ventaja es que www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
es posible eliminar elementos del principio de la lista y del medio de manera muy eficiente. Para eliminar un elemento solamente hay que modificar a sus dos “vecinos” para que se “conecten” entre sí ignorando al elemento que se está borrando. Como en una cadena, se retira un eslabón abriendo los eslabones adyacentes al que se eliminá y cerrándolos de modo que lo excluyan. No es necesario hacerle ningún cambio al resto de los elementos de la lista. En éste tipo de lista hay que tener en cuenta algunas particularidades en cuanto a rendimiento. Su método get(posicion) es particularmente lento porque necesita recorrer todos los elementos anteriores para llegar al elemento pedido. Una colección LinkedList sólo debe recorrerse mediante iteradores.
Colección Map Un Map representa lo que en otros lenguajes se conoce como “diccionario” y que se suele asociar a la idea de “tabla hash” (aunque no se implemente necesariamente con esa técnica). Un Map es un conjunto de valores, con el detalle de que cada uno de estos valores tiene un objeto extra asociado. A los primeros se los llama “claves” o “keys”, ya que nos permiten acceder a los segundos. Cuando se dice que las claves forman un conjunto, se dice en el sentido Java: Son un “Set”, en el que no puede haber duplicados. En otros lenguajes existen estructuras parecidas que admiten la existencia de claves duplicadas (a veces conocidos como “multimap”). La única manera de lograr esto en Java es haciendo que el map guarde listas de valores en vez de los valores sueltos. Un Map no es una Collection ya que esa interfaz queda demasiado pequeña. Podemos decir que Collection es unidimensional, mientras que un Map es bidimensional. No hay una manera común de expresar un Map en una simple serie de objetos que podemos recorrer. Sí podríamos recorrer una serie de objetos si cada uno de ellos representase un par {clave, valor} (y de hecho eso es cómo se debe hacer). Algunos de los métodos más importantes de un Map son: get(Object clave) Obtiene el valor correspondiente a una clave. Devuelve null si no existe esa clave en el map. put(K clave, V valor) Añade un par clave-valor al map. Si ya había un valor para esa clave, lo reemplaza. Además hay algunas funciones que son útiles a la hora de recorrer eficientemente el contenido de un Map: keySet() Devuelve todas las claves(devuelve un Set, es decir, sin duplicados). values() Devuelve todos los valores (los valores sí pueden estar duplicados, por lo tanto esta función devuelve una Collection). entrySet() Todos los pares clave-valor (devuelve un conjunto de objetos Map.Entry, cada uno de los cuales devuelve la clave y el valor con los métodos getKey() y getValue() respectivamente).
Ver Video: Alumnos Vector, en la Unidad 10, en el Módulo 1, en la plataforma elearning Laboratorio: Temperaturas Anuales www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Objetivo Comprender el funcionamiento de los arrays unidimensionales en el lenguaje Java.
Enunciado: Vamos a realizar una aplicación en la que le pediremos al usuario que introduzca las temperaturas para cada mes del año. Si el usuario no pone una temperatura para un mes, se lo volveremos a pedir hasta que rellene los doce meses. A continuación, mostraremos, la temperatura máxima, la temperatura mínima y la media anual.
Solución: CÓDIGO JAVA import java.io.*; public class ClaseTemperaturasAnuales { public static void main(String[] args) throws IOException { System.out.println("Temperaturas anuales"); BufferedReader lector=new BufferedReader(new InputStreamReader(System.in)); String[] meses = {"Enero", "Febrero", "Marzo", "Abril" , "Mayo", "Junio", "Julio", "Agosto" , "Septiembre", "Octubre", "Noviembre", "Diciembre"}; int[] temperaturas = new int[12]; int maximo, minimo; double media = 0; String dato = ""; www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
int contador = 1; int temp; while (contador <= 12) { System.out.println("Introduzca la temperatura para el mes de: " + meses[contador - 1]); dato = lector.readLine(); temp = Integer.parseInt(dato); temperaturas[contador - 1] = temp; contador++; } maximo = temperaturas[0]; minimo = temperaturas[0]; for (int i = 1; i < temperaturas.length; i++) { if (temperaturas[i] > maximo) { maximo = temperaturas[i]; } if (temperaturas[i] < minimo) { minimo = temperaturas[i]; } media += temperaturas[i]; } media = media / 12; System.out.println("--------------------------------------------------------"); System.out.println("Datos de las temperaturas anuales"); System.out.println("La temperatura maxima es: " + maximo); System.out.println("La temperatura minima es: " + minimo); System.out.println("La media anual es: " + media); System.out.println("--------------------------------------------------------"); System.out.println("Fin de programa"); }
Actividades “Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades que encontrará en la unidad correspondiente de la plataforma eLearning”.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Unidad 11. Implementando herencia Introducción Un objeto siempre pertenecerá a una familia, ya estemos hablando dentro del concepto de programación o del concepto dentro del mundo real. Si nos ponemos como ejemplo el mundo real, cualquier objeto que pensemos pertenece a una familia y podemos ir ascendiendo niveles hasta encontrar puntos en común con otro objeto, por muy diferentes que sean, es decir, podemos englobar los objetos dentro de varios conjuntos. Por ejemplo, si pensamos en un móvil y un mp3, los dos tienen características similares, pero dentro del mismo nivel no podemos englobarlos. Un mp3 es un reproductor de música, mientras que un móvil nos permite realizar llamadas, pero si subimos niveles, podemos englobar los dos objetos dentro del mismo conjunto, que puede ser los aparatos electrónicos de bolsillo, por ejemplo. A éste concepto se le conoce como abstracción y es una de las bases dentro de la herencia, saber manejar cualquier objeto por sus similitudes con otros objetos. Dichas similitudes se basan en familias o paquetes. Dentro de un mismo paquete podemos encontrar objetos que son similares aunque tengan características diferentes y algunas en común. Dichas similitudes corresponden a la herencia. Cualquier objeto que herede de otro, inmediatamente deriva todos sus métodos y características, pudiendo implementarlas.
Objetivo Manejar el conjunto de clases para implementar la herencia entre objetos y su utilización dentro del conjunto de la programación orientada a objetos.
Herencia En programación orientada a objetos, la herencia indica que una clase es una extensión de otra. Es decir, una clase es como otra y además tiene algún tipo de característica propia que la diferencia. A éste concepto se le llama implementación de una clase, y es básicamente la herencia. En Java todas las clases heredan de una clase “superior”. Aunque no implementemos el concepto de herencia y no lo indiquemos de forma explicita, todas las clases heredan de object. La clase object en Java es la clase super de cualquier clase y es el principio de la jerarquía de objetos de Java, podemos afirmar que todos los objetos son objetos de la clase object. Por ejemplo, si nos fijamos en el siguiente gráfico de clases y objetos:
Podemos perfectamente diferenciar la herencia de forma gráfica. La clase super es el coche, que es de dónde derivan y van a heredar el resto de clases. Un coche puede contener una serie de www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
características. Dichas características las contendrán todos los objetos que hereden de la clase coche, es decir, todos los objetos por debajo de coche son un coche, pero mejorado. Un Todo Terreno es un coche, pero además se le han hecho una serie de modificaciones, pero dichas modificaciones no cambian el concepto de coche, sino que lo “mejoran” para adaptarlo a un 4x4. Dependiendo del nivel dónde nos encontremos, la herencia puede comenzar en un lugar o en otro diferente. Por ejemplo, un Formula 1 es un coche. Pero un Formula 1 es más bien, un deportivo mejorado. Si heredamos de coche, tendríamos que hacer lo mismo que con un deportivo, y además, implementar el Formula 1. Si heredamos directamente de deportivo (recuperamos todas las características de un deportivo), solamente tendremos que implementar el Formula 1. Podemos ver fácilmente ésta representación gráfica en un ejemplo. Vamos a implementar la clase coche para visualizar al completo toda la estructura de la herencia y cómo podemos cambiar la lógica de los objetos implementando la herencia, para aprovechar todas sus virtudes. Nos creamos la clase Coche: public class Coche { protected int numeromarchas; private String marca; private String modelo; protected int VelocidadMaxima; private int velocidad; public Coche() { this.numeromarchas = 5; this.marca = ""; this.modelo = ""; this.VelocidadMaxima = 160; this.velocidad = 0; System.out.println("Construyendo un coche"); System.out.println("La velocidad máxima de un coche es: " + this.VelocidadMaxima); } public void setMarca(String m) { this.marca = m; } public String getMarca() { return this.marca; } public void setModelo(String m) { this.modelo = m; } public String getModelo() { return this.modelo; } public int getVelocidad(int vel) { return this.velocidad; } } Como hemos visto a lo largo de otros módulos, ponemos las variables miembro cómo privadas y accedemos a los elementos mediante sus métodos.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Hemos dejado algunas variables cómo protected para que las clases que hereden de Coche puedan modificar sus valores y adaptarlos a su nuevo cambio. Ahí es dónde vamos a ver la clave y las ventajas de la herencia. Lo que vamos a hacer a continuación será crearnos dos métodos de objeto para acelerar o frenar el coche. public void acelerarCoche() { if (this.velocidad < this.VelocidadMaxima) { this.velocidad += 40; System.out.println("Su velocidad actual es: " + this.velocidad); }else { System.out.println("Velocidad Máxima alcanzada: " + this.VelocidadMaxima); this.velocidad = this.VelocidadMaxima; System.out.println("Su velocidad actual es: " + this.velocidad); } } public void frenarCoche() { if (this.velocidad > 0) { this.velocidad -= 40; System.out.println("Su velocidad actual es: " + this.velocidad); }else { System.out.println("El coche esta detenido"); this.velocidad = 0; System.out.println("Su velocidad actual es: " + this.velocidad); } } Lo que estamos implementando en el ejemplo es lo siguiente: Un coche no puede acelerar más que su VelocidadMaxima. Por lo tanto, podemos afirmar sin ningún tipo de duda que todos los coches no pueden acelerar más de 160 km/h, tal y cómo hemos puesto en el constructor de Coche: this.VelocidadMaxima = 160; A continuación, nos vamos a crear un método en la clase Coche para mostrar el menú personalizado para el conductor. public void mostrarMenu() { System.out.println("-------------------------------"); System.out.println("1.- Acelerar"); System.out.println("2.- Frenar"); System.out.println("3.- Salir"); System.out.println("Seleccione una opcion"); System.out.println("-------------------------------"); } Ahora vamos a crearnos una clase que utilice el Coche llamada conductor, para visualizar que el funcionamiento es correcto y que nuestro supuesto es correcto: import java.io.*; public class Conductor { www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
public static void main(String args[]) throws IOException { BufferedReader lector=new BufferedReader(new InputStreamReader(System.in)); Coche c = new Coche(); int opcion = 0; while (opcion != 3) { c.mostrarMenu(); opcion = Integer.parseInt(lector.readLine()); switch (opcion) { case 1: c.acelerarCoche(); break; case 2: c.frenarCoche(); break; } } System.out.println("Hasta pronto"); } } Si utilizamos la clase conductor, visualizaremos el menú y la velocidad máxima del Coche (160 km/h) nada más construirlo.
Si ahora vamos seleccionando la opción de acelerar, podremos comprobar que el funcionamiento es correcto y que no podemos sobrepasar la velocidad máxima.
Con todo esto, hemos montado una lógica para poder conducir un coche. continuación será crearnos un objeto Deportivo que heredará de Coche:
Lo que haremos a
public class Deportivo extends Coche { public Deportivo() { } www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
} Con esta definición un Deportivo es un Coche. Son exactamente iguales y no existe ningún rasgo distintivo, el Deportivo hereda todas las características del Coche, incluida la velocidad máxima. Para comprobarlo, bastaría con ir a la clase Conductor y cambiar la siguiente línea: Coche c = new Coche(); por la siguiente declaración: Deportivo c = new Deportivo(); Si ahora utilizamos la clase conductor, el funcionamiento será el mismo que con un coche. Aprendido el concepto de herencia de miembros y métodos, ahora vamos a implementar la clase Deportivo. Un deportivo es más veloz que un coche, por lo que tenemos que incrementar la velocidad de un deportivo. Una vez que tenemos claras esas cuestiones, debemos saber que un Coche es la clase superior (super) del objeto Deportivo (clase base). Para acceder a la clase superior desde la clase base, se utiliza la palabra clave super. Para referirnos a los objetos de la clase base se utiliza la palabra clave this, tal y como hemos visto en otros capítulos. Ahora que sabemos el concepto, vamos a continuar con el supuesto de la velocidad. Un deportivo es más veloz que un coche y siempre lo será. Si la tecnología avanza y el coche se vuelve más rápido, el Deportivo siempre será más rápido que un Coche. Podriamos modificar la clase Deportivo, de forma que su velocidad máxima sea superior a la de un Coche de la siguiente forma: public class Deportivo extends Coche { public Deportivo() { this.VelocidadMaxima = 240; } } Si lo hacemos de la siguiente forma, estamos haciendo que un Deportivo sea más veloz que un coche, pero eso es algo temporal. Si incrementamos la velocidad de la clase Coche, no se incrementa la velocidad de un Deportivo, sino que siempre será la misma, no superior a la velocidad de un coche. Como el coche y el deportivo están relacionados, debemos hacer que un Deportivo sea más veloz que el coche siempre. Eso lo hacemos con la palabra clave super. Si accedemos a la velocidad máxima del coche y la incrementamos en deportivo, siempre un Deportivo será más rápido que un Coche. Podemos visualizarlo de la siguiente forma: public class Deportivo extends Coche { public Deportivo() { super.VelocidadMaxima += 80; } } Esto sería realmente lo correcto, si ahora modificasemos la velocidad máxima de la clase super (coche), siempre se incrementaría dicha velocidad máxima en 80, por lo que podemos afirmar de forma rotunda que un Deportivo siempre será más veloz que un coche. Otros conceptos que podemos realizar sobre el deportivo es la adaptación de métodos propios de la clase Deportivo. Por ejemplo, en nuestro caso, puede que necesitemos implementar las características de un deportivo, como pudiera ser un método para cambiar marchas: www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
public void cambiarMarcha() { System.out.println("Cambio de marcha en deportivo"); } Si añadimos algo al deportivo, deberíamos de poder ofrecérselo al conductor. El problema lo tenemos con el menú. Ahora mismo, el menú de un Coche y un Deportivo son iguales, pero necesitamos que el menú del Deportivo sea diferente. No queremos modificarlo, sino que deseamos cambiarlo. Dicho concepto en la herencia se llama sobreescritura de métodos. Lo hemos visto en otros capítulos el concepto, ahora vamos a llevarlo a la práctica. Simplemente, bastaría con escribir el método en la clase base (Deportivo) y modificar su contenido para adaptarlo a las nuevas características. public void mostrarMenu() { System.out.println("-------------------------------"); System.out.println("1.- Acelerar"); System.out.println("2.- Frenar"); System.out.println("3.- Cambiar Marcha"); System.out.println("4.- Salir"); System.out.println("Seleccione una opcion"); System.out.println("-------------------------------"); } Ahora son diferentes el menú de coche y del deportivo. mostrarMenu, pero cada uno es diferente en cada objeto.
Siguen teniendo el mismo método
Por último, podemos adaptar el constructor del Deportivo a nuestra conveniencia. public Deportivo() { this.numeromarchas = 6; super.VelocidadMaxima += 80; System.out.println("La velocidad maxima de un Deportivo es: " + this.VelocidadMaxima); } El constructor del objeto Coche seguirá realizandose, debido a que para construir un Deportivo será necesario construir un Coche. Pero hemos adaptado las acciones del constructor para “personalizar” el Deportivo. Ahora podemos probar las características en el objeto Conductor, pero modificando un caso más para poder implementar el método Cambiar Marcha. import java.io.*; public class Conductor { public static void main(String args[]) throws IOException { BufferedReader lector=new BufferedReader(new InputStreamReader(System.in)); Deportivo c = new Deportivo(); int opcion = 0; while (opcion != 4) { c.mostrarMenu(); opcion = Integer.parseInt(lector.readLine()); switch (opcion) { case 1: c.acelerarCoche(); www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
break; case 2: c.frenarCoche(); break; case 3: c.cambiarMarcha(); break; } } System.out.println("Hasta pronto"); } } Como podemos comprobar, en el momento de construir un Deportivo, también se construye un coche, por eso se visualizan los dos mensajes. Pero lo último que quedaría según podemos ver es la velocidad del objeto que estamos utilizando (240 km/h).
Otra de las ventajas de la herencia es la abstracción. Gracias a lo que hemos realizado, podemos manejar un Deportivo igual que un coche. Es decir, conducir un coche y un deportivo es lo mismo, sólo que un deportivo tiene más características como la velocidad máxima o el cambio de marchas, pero el funcionamiento es el mismo por parte del conductor.
Ver Video: Implementación Herencia, en la Unidad 11, en el Módulo 1, en la plataforma elearning Laboratorio: Proyecto clases agenda Objetivos: Manejar las colecciones y la interacción de clases dentro de un proyecto.
Enunciado: www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
Realizar un programa en el que controlaremos el listado de una agenda de contactos. Mostraremos el siguiente Menú:
Insertar Contacto
Mostrar Contacto
Buscar Contacto
Salir
Se realizarán las siguientes acciones: 1. Insertaremos el nombre del contacto, su teléfono y su código 2. Mostraremos todos los contactos de la agenda con sus datos personales 3. Buscaremos un contacto, con la posibilidad de buscar mediante el código o el nombre. Una vez encontrado, mostraremos sus datos asociados. 4. Salir del programa. Crearemos una clase persona para recuperar desde un único objeto las características del contacto. (Nombre, Teléfono y Código) Como reto, intentar realizar el mismo ejemplo pero con las opciones de eliminar y modificar contacto, además de crear métodos para las acciones que en la solución son repetitivas.
Solución: CODIGO JAVA CLASE PERSONA public class Persona { private String nombre; private int telefono; private short codigo; public String getNombre() { return this.nombre; } public void setNombre(String nom) { this.nombre = nom; } public int getTelefono() { return this.telefono; } public void setTelefono(int tlf) { this.telefono = tlf; } public short getCodigo() { return this.codigo; } public void setCodigo(short cod) { www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
}
this.codigo = cod; } public Persona(String nombre,int telefono, short codigo) { this.nombre=nombre; this.telefono=telefono; this.codigo=codigo; }
CLASE AGENDA CONTACTOS import java.io.*; import java.util.*; public class Agenda { public static void main(String args[]) throws IOException { Vector
miagenda = new Vector(); Persona contacto = null; BufferedReader lector = new BufferedReader(new InputStreamReader(System.in)); int opcion = 0; while (opcion != 4) { mostrarMenu(); System.out.println("Introduzca una opcion"); opcion = Integer.parseInt(lector.readLine()); switch (opcion) { case 1: String nom; int tlf,cod; System.out.println("Introduzca nombre:"); nom = lector.readLine(); System.out.println("Introduzca Telefono:"); tlf = Integer.parseInt(lector.readLine()); System.out.println("Introduzca Codigo:"); cod = Integer.parseInt(lector.readLine()); contacto=new Persona(nom,tlf,(short)cod); miagenda.addElement(contacto); break; case 2: for (int i=0; i< miagenda.size(); i++) { contacto = miagenda.elementAt(i); System.out.println("Contacto: "+contacto.getNombre()+", Telefono: "
+contacto.getTelefono()+", Codigo:
"+contacto.getCodigo()); } break; case 3: int codigo=0; String nombre=""; int seleccion; System.out.println("Seleccione una opcion de busqueda"); System.out.println("\n1.-Nombre"); www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
System.out.println("2.- Codigo"); seleccion=Integer.parseInt(lector.readLine()); boolean encontrado = false; switch (seleccion) { case 1: System.out.println("Introduzca el NOMBRE a buscar"); nombre=lector.readLine(); for (int i=0; i< miagenda.size(); i++) { contacto = miagenda.elementAt(i); if (contacto.getNombre().equals(nombre)==true) { encontrado = true; break; } } if (encontrado == true) { System.out.println("Contacto: "+contacto.getNombre()+", Telefono: " contacto.getTelefono()+", Codigo: "+contacto.getCodigo()); }else{ System.out.println("No se ha encontrado el contacto"); } break; case 2: System.out.println("Introduzca el codigo a buscar"); codigo=Integer.parseInt(lector.readLine()); for (int i=0; i< miagenda.size(); i++) { contacto = miagenda.elementAt(i); if (contacto.getCodigo() == (short)codigo) { encontrado = true; break; } } if (encontrado == true) { System.out.println("Contacto: "+contacto.getNombre()+", Telefono: " +contacto.getTelefono()+", Codigo: "+contacto.getCodigo()); }else{ System.out.println("No se ha encontrado el contacto"); } break; default: System.out.println("Opcion Incorrecta"); } break; case 4: System.exit(0); break; www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.
default: System.out.println("Opcion escrita incorrecta"); } }
} public static void mostrarMenu()
{ System.out.println("\n1.-Insertar Contacto"); System.out.println("2.-Mostrar Listin"); System.out.println("3.-Buscar Contacto"); System.out.println("4.-Salir\n"); }
}
Actividades “Recuerde que para un seguimiento óptimo de la unidad es imprescindible realizar las actividades que encontrará en la unidad correspondiente de la plataforma eLearning”.
www.learning.es Para uso exclusivo de los alumnos de LEARNING & TRAINING CLOUD, S.L.