Libro i. ibm.

267
Core Java Código del Curso: CY420 Versión: 5.1 Guía del Estudiante Libro 1: Core Java IBM Training Worldwide Certified Material

Transcript of Libro i. ibm.

Core Java Código del Curso: CY420 Versión: 5.1

Guía del Estudiante

Libro 1: Core Java IBM Training Worldwide Certified Material

.

Información Sobre la Publicación

Esta publicación ha sido producida usando Microsoft Word 2000 y Microsoft PowerPoint 2000 para Windows.

Marcas Registradas

IBM ® es una marca registrada por International Business Machines Corporation.

Otras compañías, productos, y nombre de servicios pueden ser marcas registradas o marcas de servicios de otros.

Marcas Registradas de otras Compañías

HotJava browser, Java Development Kit (JDK), Java, Java Servlet, Solaris, Enterprise Java Beans, Java Server Pages, JDK, JSP – Sun Microsystems, Microsoft MAKECAB, Windows operating system, ASP, VB, .NET, VC++, Microsoft Access, Microsoft SQL Server, Microsoft ODBC for Oracle – Microsoft Corp, WinZip – Nico Mak Computing, Inc., Time – Time Warner, JDBC – Javasoft, Oracle – Oracle Corporation, Sybase – Sybase Inc., UDB DB2 – IBM.

Edición Octubre 2007

La información contenida en este documento no ha sido sometida a ninguna prueba formal de IBM y es distribuida básicamente “como es" sin ninguna garantía ya sea expresa o implícita. El uso de esta información o la implementación de cualquiera de estas técnicas es responsabilidad del comprador y dependerá de la habilidad de éste para su evaluación e integración en el ambiente operacional del comprador. A pesar de que cada tema ha sido revisado por IBM para su exactitud en una situación específica, no hay garantía de que obtener el mismo resultado o uno similar a éste en otra situación. Los compradores que intenten adaptar estas técnicas a sus propios ambientes lo hacen bajo su propio riesgo.

Copyright International Business Machines Corporation, 2007. All rights reserved. Este documento no puede ser reproducido en su totalidad o en parte sin el previo permiso escrito de IBM.

Instrucciones Especiales para la Impresión de este Curso:

No elimine páginas en blanco que puedan aparecer al final de cada unidad o entre unidades. Estas páginas fueron insertadas intencionalmente.

Guía del Estudiante Core Java

i © Copyright IBM Corp. 2007

Los materiales del curso no pueden ser reproducidos total o parcialmente sin el previo permiso escrito de IBM.

Contenido Descripción del Curso: Core Java....................................................................iv Descripción de Unidades ................................................................................viii Volumen 1: Fundamentos de Java ....................................................................1 Unidad 1: Visión General de Java .....................................................................3

Objetivos del Aprendizaje 3 1. Introducción 4 2. Historia de Java 4 3. Comparación entre Java y C++ 5 4. Características de Java 6 5. La Plataforma Java 11 6. Impacto de Java en la WWW 16 7. Clases y Objetos 17 8. Orientación a Objetos en Java 21 9. Ejemplo de una Aplicación Java 26 10. Ejemplo de Applet Java 27 Resumen 29 Unidad 1: Examen de Autoevaluación 30 Respuestas a la Unidad 1: Examen de Autoevaluación 32

Unidad 2: Operadores, Expresiones y Control de Flujo................................33 Objetivos del Aprendizaje 33 1. Introducción 34 2. Tipos de Datos en Java 34 3. Clases Envolventes 39 4. Math Clases Colaboradoras sobre los Tipos de Datos 44 5. Manejo de String 44 6. Identificadores 50 7. Declaración e Inicialización de Variables 51 8. Operadores en Java 53 9. Conversión de Tipos 63 10. Arreglos 66 11. Estructuras de Control 71 Resumen 86 Unidad 2: Examen de Autoevaluación 87

Core Java Guía del Estudiante

ii © Copyright IBM Corp. 2007

Los materiales del curso no pueden ser reproducidos total o parcialmente sin el previo permiso escrito de IBM.

Respuestas a la Unidad 2: Examen de Autoevaluación 89 Unidad 3: Lab. de Operaciones, Expresiones y Control de Flujo.................90

Objetivos del Aprendizaje 90 Ejercicios de Laboratorio 91

Volumen 2: Programación Orientada a Objetos.............................................95 Unidad 1: Clases y Objetos..............................................................................97

Objetivos del Aprendizaje 97 1. Introducción 98 2. Clases y Objetos 98 3. Estructura de una Clase Java 101 4. Variables 103 5. Métodos 108 6. Modificadores de Acceso 113 7. Constructores de una Clase 121 8. Sobrecarga de Método 124 9. Clases Anidadas 127 10. Argumentos de Línea de Comandos 130 11. Ciclo de Vida de un Objeto 131 12. Manejo de la Memoria en Java 136 13. Enumeraciones 136 Resumen 138 Unidad 1: Examen de Autoevaluación 139 Respuestas a Unidad 1: Examen de Autoevaluación 141

Unidad 2: Laboratorio de Clases y Objetos..................................................143 Objetivos del Aprendizaje 143 Ejercicios de Laboratorio 144

Unidad 3: Herencia .........................................................................................147 Objetivos del Aprendizaje 147 1. Introducción 148 2. Sintaxis para Declarar Clases Usando Herencia en Java 148 3. Conceptos Esenciales de Herencia 152 Resumen 177 Unidad 3: Examen de Autoevaluación 178 Respuestas a la Unidad 3: Examen de Autoevaluación 180

Unidad 4: Laboratorio de Herencia ...............................................................181 Objetivos de Aprendizaje 181

Guía del Estudiante Core Java

iii © Copyright IBM Corp. 2007

Los materiales del curso no pueden ser reproducidos total o parcialmente sin el previo permiso escrito de IBM.

Ejercicios de Laboratorio 182 Unidad 5: Clases Abstractas e Interfaces.....................................................183

Objetivos de Aprendizaje 183 1. Introducción 184 2. Clases Abstractas 184 3. Uso de Clases Abstractas 186 4. ¿Qué son las Interfaces? 194 5. Usar Interfaces Como Referencias 202 6. Heredar de una Interfaz 205 7. Opciones de Herencia en Java 208 Resumen 210 Unidad 5: Examen de Autoevaluación 211 Respuestas a la Unidad 5: Examen de Autoevaluación 213

Unidad 6: Laboratorio de Clases Abstractas e Interfaces...........................215 Objetivos de Aprendizaje 215 Ejercicios de Laboratorio 216

Unidad 7: Paquetes.........................................................................................219 Objetivos de Aprendizaje 219 1. Introducción 220 2. Necesidad de los Paquetes 220 3. Crear Paquetes en Java 222 4. Representación del Paquete en el Sistema de Archivos 224 5. Paquetes y Protección de Acceso 227 6. Usar Miembros de Paquetes 235 7. Agrupar Paquetes 239 8. Despliegue de Paquetes 239 9. Paquetes Incorporados en Java Usados Comúnmente 245 Resumen 248 Unidad 7: Examen de Autoevaluación 249 Respuestas a la Unidad 7: Examen de Autoevaluación 251

Core Java Guía del Estudiante

iv © Copyright IBM Corp. 2007

Los materiales del curso no pueden ser reproducidos total o parcialmente sin el previo permiso escrito de IBM.

Descripción del Curso: Core Java Nombre del Curso Core Java Duración La duración del curso es de 108 horas. Propósito Este curso ofrece a los estudiantes un estudio del lenguaje Java. El primer volumen del curso se ocupa de los fundamentos de Java, del impacto de Java en la Web, la orientación a objetos en Java, operadores y estructuras de control. Los estudiantes aprenderán sobre las características de Java, convenciones de nombres, declaración de variables y su inicialización.

El segundo volumen del curso se ocupa de la programación orientada a objetos. Proporciona una descripción de los miembros de una clase Java, del uso de los métodos de clase y del manejo de la memoria en Java. Los estudiantes aprenderán sobre los fundamentos de la herencia, de clases, métodos abstractos y las interfaces. También aprenderán sobre los paquetes incorporados comúnmente usados de Java.

El tercer volumen del curso trata de las excepciones y los métodos para lanzar excepciones. Los estudiantes aprenderán cómo distinguir entre las excepciones verificadas y no verificadas. También aprenderán sobre cómo crear y usar excepciones definidas por el usuario.

El cuarto volumen del curso proporciona una descripción de las capacidades para entrada/salida. Trata de los archivos y los flujos, los flujos de caracteres, las clases lectoras y escritoras, además de los archivos de acceso aleatorio. También se ocupa de la serialización de objetos, de la interfaz serializable y de la interfaz externalizable. Los estudiantes estudiarán la clase ObjectOutputStream y la clase ObjectInputStream.

El quinto volumen del curso provee una descripción de las interfaces de usuario usando AWT y Swing. Se ocupa de las clases y contenedores de AWT, dibujo y actualización de los componentes de la interfaz del usuario. También trata los métodos heredados por los componentes de AWT de las clases componente y contenedor. Los estudiantes aprenderán sobre los administradores de diseño, además de asociarlos al contenedor. Adicionalmente, obtendrán información sobre el modelo de delegación de eventos y el manejo de eventos.

Se proporciona una introducción a ciertas clases fundamentales de Java. Se ocupa de la arquitectura MVC y las clases Swing, las diferencias entre AWT y Swing, los componentes Swing, el API de Java 2D y la representación en 2D.

El sexto volumen del curso introduce a los applets. Se ocupa del ciclo de vida de un applet, prueba de applets, carga de un applet, métodos de dibujo y manejo de eventos.

Guía del Estudiante Core Java

v © Copyright IBM Corp. 2007

Los materiales del curso no pueden ser reproducidos total o parcialmente sin el previo permiso escrito de IBM.

Los estudiantes aprenderán conceptos tales como: usar el API de applet, localizar y cargar archivos de datos, mostrar documentos en un navegador web, comunicación con otros applet y restricciones de seguridad en applets.

El séptimo volumen del curso contiene una introducción a multihilos y redes. Estudia el ciclo de vida de los hilos, creación y funcionamiento, realizar subclases de la clase de hilo e implementar la interfaz Runnable. También se ocupa de la sincronización de hilos, de los métodos y sentencias sincronizadas, además de la comunicación entre hilos. Los estudiantes aprenderán sobre el trabajo con URLs y programación de conectores, clases orientadas a conexión en Java, envío y recepción de datagramas.

El octavo volumen de este curso presenta una descripción del API de colecciones. Se ocupa del marco de trabajo para colecciones de Java, de las interfaces e implementaciones de las colecciones. Presenta la conectividad a la base de datos en Java y las sentencias SQL usadas en los programas Java, además de los pasos que implica el acceso a base de datos. Los estudiantes aprenderán sobre procedimientos almacenados, manejo de la transacción, soporte de cursores, procesamiento de múltiples conjuntos de resultados, entre otras funcionalidades de JDBC. Para finalizar se discute acerca de las características avanzadas, tales como: las consideraciones de seguridad cuando se trabaja con programas Java, los Java beans y los conceptos de la internacionalización.

El curso incorpora varias sesiones de laboratorios donde los estudiantes obtendrán experiencia práctica en los conceptos de Core Java.

Audiencia Estudiantes, Profesionales y Gente de Negocios. Prerrequisitos CY410, CY350

Core Java Guía del Estudiante

vi © Copyright IBM Corp. 2007

Los materiales del curso no pueden ser reproducidos total o parcialmente sin el previo permiso escrito de IBM.

Objetivos Al completar este curso, usted será capaz de:

• Entender las características principales de Java. • Explicar los principios de orientación a objetos en Java. • Explicar las diferentes estructuras de control usadas en Java. • Explicar la necesidad y el uso de los constructores de una clase. • Describir cómo se realiza el manejo de la memoria en Java. • Describir cómo crear jerarquías de herencia. • Definir y explicar cómo implementar una interfaz. • Explicar la variable classpath y describir su uso. • Discutir las excepciones y las técnicas tradicionales para el manejo de errores. • Describir el manejo de excepciones en Java. • Examinar las diferentes formas en las que las excepciones pueden ser lanzadas,

capturadas y manejadas. • Exponer la clase File. • Explicar los diferentes flujos de caracteres y de byte. • Explicar la interfaz Serializable y la clase ObjectInputStream. • Describir algunas clases útiles y algunos GUI en AWT. • Explicar cómo escoger un administrador de diseño y sus responsabilidades. • Explicar cómo implementar el mecanismo de delegación de eventos. • Describir la arquitectura MVC. • Explicar los administradores de diseño definidos en Swing. • Describir las propiedades de la apariencia de Swing. • Establecer las diferencias entre un applet y una aplicación. • Describir los métodos para agregar componentes de UI. • Mencionar las ventajas del API Applet. • Explicar los conceptos de hilos y multihilos. • Explicar cómo crear hilos desde la clase Thread y desde la interfaz Runnable. • Describir el concepto de sincronización. • Explicar los métodos y sentencias sincronizadas. • Exponer los URLs y las excepciones de URL. • Explicar los conectores orientados a conexión y no orientados a conexión. • Describir las interfaces de colecciones. • Describir los algoritmos polimórficos del JDK que operan en las colecciones. • Discutir el API de JDBC. • Explicar el manejo de excepciones en JDBC.

Guía del Estudiante Core Java

vii © Copyright IBM Corp. 2007

Los materiales del curso no pueden ser reproducidos total o parcialmente sin el previo permiso escrito de IBM.

• Explicar el uso de PreparedStatement y CallableStatement en JDBC. • Mencionar algunas de las clases de soporte de JDBC en Java. • Explicar la manipulación de objetos de una clase. • Exponer las características de seguridad cuando se trabaja con programas Java. • Explicar el empaquetamiento de componentes Java. • Exponer el API Java 2D.

Agenda Cada unidad en este curso es de 2 horas de duración.

Core Java Guía del Estudiante

viii © Copyright IBM Corp. 2007

Los materiales del curso no pueden ser reproducidos total o parcialmente sin el previo permiso escrito de IBM.

Descripción de Unidades Volumen 1: Fundamentos de Java Unidad 1: Visión General de Java

Esta unidad introductoria proporciona una visión general de Java, incluyendo la historia del desarrollo de Java, fundamentos básicos de la Programación Orientada a Objetos y aspectos básicos de Java. También cubre la plataforma de Java y su efecto en la WWW.

Unidad 2: Operadores, Expresiones y Flujo de Control

Esta unidad se ocupa de los elementos fundamentales de Java: tipos de datos y variables, diferentes tipos de operadores en Java y de la precedencia de operadores. También se discuten las conversiones de tipo y las estructuras de control en Java.

Unidad 3: Laboratorio de Operadores, Expresiones y Flujo de Control

Esta unidad de Laboratorio permite al estudiante poner en práctica algunos de los aspectos fundamentales de Java, como operaciones aritméticas, operadores de bits y lazos en Java. Esta actividad se realiza a través de un pequeño conjunto de ejercicios.

Volumen 2: Programación Orientada a Objetos Unidad 1: Clases y Objetos

El concepto de una clase, el ciclo de vida de un objeto y los constructores de una clase son algunos de los tópicos tratados en esta unidad. Esta unidad también examina las especificaciones para el control del acceso, cómo declarar variables miembro, métodos miembro, la manera de acceder a las clases utilizando métodos estáticos, métodos sobrecargados y argumentos en la línea de comandos. Finalmente, se ofrece una visión general sobre el recolector de basura.

Unidad 2: Laboratorio de Clases y Objetos

En esta unidad se desarrollan ejercicios de laboratorio para crear clases y objetos, llamar métodos de una clase y sobrecargar métodos de una clase. También proporciona una ruta de experiencia práctica acerca de los paquetes, el CLASSPATH y su utilización, la protección de acceso mientras se usan los paquetes, miembros de paquetes y cómo importar paquetes. También le permite al estudiante tener una visión general de los paquetes intrínsecos de Java más usados.

Unidad 3: Herencia

El principal objetivo de esta unidad es entender los aspectos básicos de la herencia, cómo utilizar el modificador súper, cómo crear la herencia multi-nivel y los fundamentos del método de sobreescritura. También se discute el uso de la palabra clave final para evitar la sobreescritura y para evitar la herencia.

Guía del Estudiante Core Java

ix © Copyright IBM Corp. 2007

Los materiales del curso no pueden ser reproducidos total o parcialmente sin el previo permiso escrito de IBM.

Unidad 4: Laboratorio de Herencia

Esta unidad de laboratorio permite al estudiante tener una mejor comprensión del concepto de herencia y cómo llamar a los métodos de la clase base.

Unidad 5: Clases Abstractas e Interfaces

En esta unidad se discute acerca del modificador abstract y las clases y métodos abstractos. También se discuten las interfaces, su implementación total o parcial, el uso de interfaces y referencias, las variables de una interfaz y cómo heredar desde una interfaz.

Unidad 6: Laboratorio de Clases Abstractas e Interfaces

Esta unidad de laboratorio le ofrece parcialmente al estudiante una exposición del uso de las clases abstractas y la necesidad de usar interfaces.

Unidad 7: Paquetes

Los paquetes son un aspecto importante en el estudio de Java. En esta unidad se define qué es un paquete, el CLASSPATH y su utilización, además de la protección de acceso mientras se usan los paquetes. También explica cómo utilizar los paquetes miembro, cómo importar paquetes y se explican algunos de los paquetes intrínsecos de Java más utilizados.

Volumen 3: Manejo de Excepciones Unidad 1: Manejo de Excepciones y Tipos de Excepciones

El lenguaje Java proporciona algunos mecanismos sofisticados para el manejo de excepciones, en comparación con otros lenguajes de programación modernos. Esta unidad establece qué es una excepción y discute la importancia del manejo de excepciones. Proporciona una breve visión del manejo de excepciones en los lenguajes de programación y cómo se aplica en Java. Se examinan los tipos de excepciones, su jerarquía en Java, las declaraciones try y catch, así como la cláusula finally en Java. Proporciona una visión de las excepciones en tiempo de ejecución (runtime) y los diferentes métodos para el lanzamiento y propagación de excepciones.

Unidad 2: Lanzamiento y Manejo de Excepciones

Esta unidad trata con los métodos de lanzamiento de excepciones, métodos para manejar excepciones y las diferentes formas en que las excepciones pueden ser lanzadas, capturadas y manipuladas. También se discute el método mediante el cual se crean y usan las excepciones definidas por el usuario.

Unidad 3: Laboratorio de Lanzamiento y Manejo de Excepciones

Basándose en las unidades 1 y 2, esta unidad de Laboratorio proporciona una ruta para experimentar en forma práctica cómo manejar excepciones, como usar las cláusulas

Core Java Guía del Estudiante

x © Copyright IBM Corp. 2007

Los materiales del curso no pueden ser reproducidos total o parcialmente sin el previo permiso escrito de IBM.

throw y catch aparte de dominar el uso de la cláusula throws. También permite al estudiante aprender a escribir excepciones definidas de usuario.

Volumen 4: Facilidades de Entrada / Salida Unidad 1: Archivos y Flujos

Esta unidad trata los conceptos File, FileDescriptor, flujos, flujos de caracteres, flujos byte y acceso aleatorio de archivos.

Unidad 2: Laboratorio de Archivos y Flujos

Esta unidad provee un conjunto de ejercicios para aprender acerca de creación de archivos, lectura y escritura desde y hacia archivos. También provee ejercicios para acceder a directorios y subdirectorios.

Unidad 3: Serialización de Objetos

La serialización de Objetos es un tópico importante en Java y esta unidad trata sobre ese tema, la interfaz Serializable, la interfaz Externalizable, la clase ObjectOutputStream y la clase ObjectInputStream.

Unidad 4: Laboratorio de Serialización de Objetos

Esta unidad de laboratorio se construye sobre la base conceptual de la unidad 3 y le permite al estudiante aprender a realizar la serialización de Objetos en Java.

Volumen 5: Crear Interfaces Usando AWT y Swing Unidad 1: Componentes y Contenedores AWT

En esta unidad se discute el ‘abstract window toolkit –AWT- (grupo de programas de ventana abstracta), algunas clases útiles en AWT y algunos componentes GUI en AWT.

Unidad 2: Laboratorio de Componentes y Contenedores AWT

Este laboratorio le permite al estudiante aprender a usar varios controles que se incluyen en el AWT, a crear y manejar ventanas y a usar las clases MenuBar, Menu y FileDialog.

Unidad 3: Administradores de Diseño (Layout Managers)

Esta unidad ofrece una amplia cobertura de los manejadores de diseño y su selección. Se discuten los diferentes administradores de diseño, sus responsabilidades y las reglas para su aplicación y uso.

Guía del Estudiante Core Java

xi © Copyright IBM Corp. 2007

Los materiales del curso no pueden ser reproducidos total o parcialmente sin el previo permiso escrito de IBM.

Unidad 4: Laboratorio de Administradores de Diseño (Layout Managers)

En esta unidad de laboratorio, los estudiantes practican el uso de varios manejadores de diseño y trabajan en la creación de varios controles como TextField, TextArea, CheckboxGroup y Button.

Unidad 5: Modelo de Delegación de Eventos y Manejo de Eventos

Esta unidad examina el Modelo de Conducción de Eventos, los ‘Listeners’ (Oyentes) y ‘Adapters’ (Adaptadores). También provee una manera de implementar el mecanismo de conducción de eventos.

Unidad 6: Laboratorio de Modelo de Delegación de Eventos y Manejo de Eventos

En esta unidad de laboratorio el estudiante aprende el mecanismo de manejo de eventos y el uso de la clase PopupMenu.

Unidad 7: Arquitectura MVC y Clases Swing

En esta unidad se discuten en gran detalle la arquitectura MVC y los componentes Swing. La mayoría de los componentes se analizan en detalle, con ejemplos ilustrativos.

Unidad 8: Componentes Swing

Esta unidad trata con las clases swing, las propiedades look y feel (Apariencia) de Swing y el API Java 2D. Se incluyen detalles de todas las clases y ejemplos dados.

Unidad 9: Laboratorio de Componentes Swing

En esta unidad de Laboratorio, se espera que los estudiantes entiendan el uso del componente Swing y las características de las clases Swing.

Volumen 6: Applets Unidad 1: Escribir y Desplegar Applets

En el lenguaje Java, los applets son uno de los tópicos más interesantes y significativos. Esta unidad establece qué es un applet y lo que puede hacer. Provee un resumen de los applets, su ciclo de vida y cada una de sus fases significativas. Se discuten los métodos para responder a eventos (milestones), el uso de los métodos para dibujar y manejar eventos, los métodos para añadir componentes UI y la aplicación y ventajas del API en un applet.

Unidad 2: Laboratorio de Escribir y Desplegar Applets

En esta unidad, los estudiantes aprenden a desarrollar applets sencillos, los cuales interactúan con el usuario y realizan comunicaciones entre applets a través del programa Cliente-Servidor.

Core Java Guía del Estudiante

xii © Copyright IBM Corp. 2007

Los materiales del curso no pueden ser reproducidos total o parcialmente sin el previo permiso escrito de IBM.

Volumen 7: Multihilos y Sistema de Redes Unidad 1: Crear Hilos

Java es conocido por su poder en términos de hilos. En esta unidad se discuten los conceptos de hilos y multihilos (threads y multithreading), el ciclo de vida de los hilos, el API Thread y el método de crear hilos de la clase Thread y la interfaz Runnable. También se cubren propiedades especiales de los hilos como establecer prioridades y el ThreadGroup.

Unidad 2: Laboratorio Crear Hilos

Esta unidad proporciona ejercicios para fortalecer la base conceptual presentada en la unidad 1 de creación de hilos y ayudar a escribir programas que apliquen hilos en Java.

Unidad 3: Sincronización de Hilos

En esta unidad se examinan los conceptos de sincronización, métodos sincronizados y sentencias sincronizadas. También se discuten los interbloqueos o puntos muertos (deadlocks) y provee una visión de comunicación entre hilos.

Unidad 4: Laboratorio de Sincronización de Hilos

Esta unidad ha sido diseñada para bosquejar el entorno teórico en términos de sincronización de hilos y reforzar el aprendizaje del uso de la sincronización de hilos en la solución de problemas usando Java.

Unidad 5: URLs y Programación de Conectores (Sockets)

Esta unidad trata acerca del ‘Uniform Resource Locators –URLs’ (Localizadores de Recursos Uniformes), la creación de un URL y la creación de un URL relativo a otro URL. También se discuten los tópicos de MalformedURLException, cómo analizar un URL, leyendo directamente desde un URL, cómo conectarse a un URL, cómo leer desde un objeto URLConnection, y cómo escribir a un objeto URLConnection. Por otra parte, abarca los diferentes modos de operaciones de socket, el modo orientado a conexiones de operación de sockets, etc.

Unidad 6: Laboratorio de URLs y Programación de Conectores

Esta unidad de laboratorio permite a los estudiantes practicar el uso de Java trabajando con URLs y realizar trabajos con conectores en el ámbito de programación.

Volumen 8: Conceptos Avanzados Unidad 1: API de Colecciones

Esta unidad ayuda a entender el marco de trabajo de las colecciones de Java, las interfaces de colecciones y el impacto que produjo la inclusión de los Genéricos en Java 5.0. También discute algunos algoritmos polimórficos de JDK operando en colecciones y algunas implementaciones de colecciones.

Guía del Estudiante Core Java

xiii © Copyright IBM Corp. 2007

Los materiales del curso no pueden ser reproducidos total o parcialmente sin el previo permiso escrito de IBM.

Unidad 2: Laboratorio del API de Colecciones

Esta unidad proporciona ejercicios para ayudar a entender la interfaz collection, cómo usar ArrayList, y el uso de las interfaces SortedSet, HashSet y TreeSet. También ayuda a usar la clase iterator y sus métodos.

Unidad 3: JDBC

Esta unidad trata la conectividad de base de datos en Java y el API JDBC de Java. Discute las sentencias SQL usadas en los programas de Java y cómo funciona el manejo de excepciones.

Unidad 4: Laboratorio de JDBC

Existen algunos ejercicios en esta unidad para ayudar a los estudiantes a conectarse a una base de datos a través de un programa Java, además de entender cómo acceder a la base de datos una vez que se establece una conexión.

Unidad 5: JDBC Avanzado

Se explican algunos conceptos avanzados de JDBC tales como usar las clases heredadas de Statement, procedimientos almacenados (stored procedures) y otras funcionalidades JDBC, como por ejemplo el manejo de transacciones.

Unidad 6: Laboratorio de JDBC Avanzado

Esta unidad permite al estudiante escribir código en Java para crear y usar los procedimientos almacenados, además de facilitar la comprensión acerca de la forma en que trabaja la administración de transacciones.

Unidad 7: Características Avanzadas

En esta unidad, los objetivos consisten en la capacitación del trabajo con imágenes y gráficos, incorporar elementos de seguridad mientras se trabaja con programas en Java y aprender el concepto de internacionalización en Java. También se explican los Java beans y cómo realizar la invocación remota de métodos.

Unidad 8: Laboratorio de Características Avanzadas En esta unidad, los estudiantes aprenderán a convertir un programa Java usando internacionalización y trabajarán con la invocación de métodos remotos.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 1

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Volumen 1: Fundamentos de Java

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 3

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 1: Visión General de Java

Objetivos del Aprendizaje Al final de esta unidad, usted será capaz de:

• Discutir la evolución de Java. • Comparar Java con C++. • Discutir las características principales de Java. • Explicar la plataforma Java. • Describir el impacto de Java en WWW. • Definir clases y objetos. • Explicar los principios de orientación a objetos en Java.

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 4

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

1. Introducción Antes que Java existiera, C y C++ eran los lenguajes de programación más usados. C es un lenguaje de programación estructurada, mientras que C++ brinda soporte tanto a la programación estructurada como a la programación orientada a objetos. Estos dos lenguajes de programación son complejos y tienen algunas limitaciones inherentes. Aunque Java no fue diseñado como solución a los problemas encontrados en C o C++, algunas de sus características han solventado las limitaciones de estos dos lenguajes.

Uno de los objetivos principales detrás de la creación de Java fue tener un lenguaje orientado a objetos que fuera poderoso, pero simple. Java ha simplificado muchas de las estructuras complicadas y ambiguas de C++. Otra ventaja fundamental es que Java trajo el concepto de la independencia de plataforma. Se aprenderá acerca de estas características en detalle en las próximas secciones.

Sin embargo, antes de continuar, se presenta un breve resumen de la evolución de Java.

2. Historia de Java Patrick Naughton, Mike Sheridan y James Gosling de SUN Microsystems iniciaron un proyecto secreto llamado "Proyecto Verde" (Green Project) a finales de 1990. El objetivo de este proyecto era anticiparse a la revolución en el mundo de la computación que estaba por llegar. El equipo decidió intentar introducirse en el mercado de la electrónica de consumo y desarrollar programas para pequeños dispositivos electrónicos. Desarrollaron un dispositivo llamado StarSeven (*7), este dispositivo era capaz de controlar una variedad de plataformas de entretenimiento y dispositivos de uso doméstico, además de mostrar animaciones simultáneamente. *7 usaba un procesador independiente del lenguaje llamado Oak para adaptarse a una variedad de plataformas y dispositivos de uso doméstico. Tras unos comienzos dudosos, Sun decidió crear una filial, denominada FirstPerson Inc., para dar margen de maniobra al equipo responsable del proyecto. Este grupo intentó mercadear él *7 a la industria de televisión por cable, pero la tecnología usada para desarrollar él *7 estaba adelantada a la tecnología existente en la industria de televisión por cable y por esto no fue aceptado.

Afortunadamente para el grupo creador del *7, Internet se estaba volviendo popular en ese momento. La Internet tenía una configuración de red similar al *7, y estaba siendo usada cada vez más para la transferencia de texto, gráficos y video, esencialmente datos estáticos. El equipo FirstPerson amplió Oak, transformándolo en un lenguaje que permitía al programador escribir programas que corrían en una gran variedad de dispositivos, a un lenguaje que permitía escribir código ejecutable que podía ser distribuido en Internet.

En el año 1995, este nuevo lenguaje evolucionado fue llamado Java. Java permitía a los usuarios de Internet transferir contenido estático a través de la misma. Adicionalmente, permitía transferir pequeñas aplicaciones dinámicas a través de la red en la forma de applets de Java. Algunos de los miembros del grupo FirstPerson mostraron el lenguaje

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 5

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

y sus nuevas características, incluyendo la transferencia de animaciones a través de la Internet, en la Conferencia de Diseño, Tecnología y Entretenimiento en Monterrey. Sus características y funcionalidades asombraron a los participantes, ya que la tecnología proveía un método más sencillo para transferir datos en la Internet. El equipo pronto construyó el navegador HotJava, y publicó el código fuente Java gratuitamente en Internet. En poco tiempo, el número de usuarios de la tecnología Java se incrementó rápidamente.

A continuación se va a comparar Java y C++, ambos lenguajes de programación orientado a objetos, para descubrir que ha hecho a Java tan popular.

3. Comparación entre Java y C++ Java simplifica muchas de las ambigüedades encontradas en C++, y es, al mismo tiempo, un lenguaje de programación igualmente poderoso. Se ha visto con anterioridad las ventajas del paradigma de programación orientada a objetos.

Existen algunas deficiencias en C++, por el hecho de que permite programación estructurada. Esto ha sido eliminado en Java, que es un lenguaje puramente orientado a objetos.

Las principales diferencias entre C++ y Java se listan en la Tabla 1.1.

Java C++ Es tanto un lenguaje de programación como una plataforma de software. Es sólo un lenguaje de programación.

Es un lenguaje puramente orientado a objetos.

Da soporte tanto a la programación estructurada como a la programación orientada a objetos.

Todas las declaraciones de variables y métodos deben estar dentro de la definición de la clase.

Las declaraciones de variables y funciones pueden estar presentes fuera de las definiciones de las clases. No es necesario para un programa en C++ tener una clase.

El lenguaje es independiente de la plataforma. El código Java, una vez escrito, puede ser ejecutado en cualquier plataforma.

El código C++, una vez escrito para una plataforma, necesita ser compilado de nuevo, y el código objeto reenlazado para ser ejecutado en otra plataforma diferente.

Maneja la memoria automáticamente. Los programadores tienen que hacerse cargo de liberar la memoria no utilizada.

No se soporta características como sobrecarga de operadores y conversiones automáticas en ambos sentidos.

Da soporte a características como sobrecarga de operadores y conversiones automáticas en ambos sentidos.

Una clase no puede heredar directamente de más de una clase. Se da soporte a la herencia múltiple usando interfaces.

Una clase puede heredar directamente de más de una clase.

Tiene rutinas de librerías extensibles. Sus rutinas de librerías no son extensibles.

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 6

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

La programación de redes es más fácil. Los objetos pueden ser accedidos a través de la red usando URLs.

La programación para redes es compleja, a menos que se usen APIs de terceros. C++, es un lenguaje, que no brinda soporte incorporado para programación de redes.

Los programadores no pueden usar apuntadores. Los apuntadores se usan internamente.

Los programadores pueden usar apuntadores.

Implementa arreglos verdaderos. Se implementan los arreglos con aritmética de apuntadores.

Tabla 1.1: Comparación entre C++ y Java

Aunque las construcciones de programación de Java (sintaxis) son similares a las de C++, Java no debe ser interpretado como la versión Internet de C++, ni como un reemplazo para C++. El equipo FirstPerson contó con programadores expertos para asegurar que Java permitiera a los programadores tener un control completo sobre la ejecución del programa, excepto por las restricciones inherentes al ambiente de Internet.

Ahora se estudiarán las diversas características ofrecidas por Java.

4. Características de Java Java puede usarse para desarrollar dos tipos de programas:

Aplicaciones: Las aplicaciones son programas independientes que pueden correr en una computadora, usando la plataforma Java con el soporte del sistema operativo de la computadora.

Applets: Los applets son programas especiales Java, que pueden usarse para transmitir información en Internet.

Los applets pueden ser incrustados en una página HTML usando la etiqueta Applet, y pueden ejecutarse en un navegador web con soporte para Java. Los applets pueden adaptarse a la entrada del usuario inteligentemente. Las aplicaciones Java y los applets pueden ser compilados y ejecutados usando el Kit de Desarrollo de Java (Java Development Kit JDK).

La Figura 1.1 muestra las diferentes características de Java.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 7

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 1.1: Características de Java

4.1 Simple de Usar

El estilo de programación en Java está basado en C++, y soporta la mayoría de las características ofrecidas por C++. De aquí que, los programadores no encontrarán Java muy difícil de entender y usar. Un programador con un buen conocimiento de los conceptos de orientado a objetos puede sacar el máximo provecho a Java, ya que se implementan los conceptos en una forma mucho más sencilla que en C++.

4.2 Seguridad

Inicialmente, cuando la Internet comenzó y Java no era tan conocido, los usuarios de Internet temían descargar programas ejecutables debido al daño alarmante causado por la difusión de virus. Las personas que descargaban archivos eran muy cautelosas de revisar estos archivos cuidadosamente antes de usarlos. Había también programas maliciosos que recababan información acerca de tarjetas de crédito, palabras clave, etc. del sistema de archivos local. Esto fue, por supuesto, desastroso para las personas que navegan por la Internet. Java proporcionó un modelo de seguridad, que previene el acceso a los recursos del sistema, y así bloquear cualquier intento malicioso.

4.3 Portabilidad

Existen muchas ocasiones en donde los usuarios de Internet pueden querer descargar programas y ejecutarlos dinámicamente. Los usuarios pueden estar usando diferentes

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 8

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

tipos de plataformas, para permitirles descargar programas y ejecutarlos dinámicamente, se necesita de un mecanismo para crear código ejecutable que sea portable entre varias plataformas.

Java solventa este inconveniente de portabilidad con el uso de bytecodes. El compilador Java (javac) primero convierte el código fuente (archivo con extensión .java) a bytecodes (archivo con extensión .class), que puede entender el sistema de tiempo de ejecución de Java o la Máquina Virtual de Java (Java Virtual Machine JVM); estos bytecodes son interpretados por el intérprete de Java, y convertidos a una forma ejecutable que la entiende la plataforma en la cual el sistema de tiempo de ejecución de Java se está ejecutando.

El ambiente de tiempo de ejecución de Java es el ambiente en donde es posible que los programas puedan ser compilados y ejecutados. Este ambiente administra el manejo de la memoria y otras necesidades en tiempo de ejecución durante la ejecución del programa. La Máquina Virtual de Java (JVM) es la capa entre el microprocesador y los archivos class de Java. Realiza la funcionalidad de traducir los bytecodes de Java, a una forma entendible por la máquina.

Existe otro componente llamado el compilador ‘Just-In-Time (JIT)’. El compilador JIT compila los bytecodes a código máquina, haciéndolos más rápidos que la interpretación hecha por la JVM.

El sistema de tiempo de ejecución de Java es específico a la plataforma en la cual se ejecuta. Java soporta la portabilidad, porque los bytecodes son interpretados antes de la ejecución. La Figura 1.2, explica cómo Java logra la portabilidad.

Figura 1.2: JVM e Independencia de la Plataforma

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 9

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

El sistema de tiempo de ejecución Java previene que el código acceda a cualquier recurso fuera de él. De este modo, el sistema de tiempo de ejecución mejora las características de seguridad ya provistas por Java. Los bytecodes de Java también son útiles al mejorar el nivel de seguridad ofrecido por Java. Aún si Java hubiese sido diseñado para ser compilado justo antes de la ejecución, en vez de ser interpretado como actualmente lo es, soportaría la portabilidad. Esto se debe a que la ejecución del programa está todavía en manos del sistema de tiempo de ejecución de Java. Este método de compilación usado para convertir bytecodes a código nativo se llama compilación ‘justo a tiempo’ (Just In Time JIT).

La Figura 1.3 muestra como trabaja el compilador JIT.

Figura 1.3: Compilador JIT y la JVM

4.4 Distribuido

La computación distribuida es muy útil en el ambiente de la Internet, donde los módulos de los programas pueden estar presentes en diferentes computadoras alrededor del mundo. Java fue diseñado para brindar soporte TCP/IP. El soporte a redes de Java permite construir aplicaciones cliente/servidor, adicionalmente Java tiene el paquete de Invocación de Métodos Remota (Remote Method Invocation RMI). Este permite a programas que se ejecutan en una JVM invocar un método en una clase Java ejecutándose en otra JVM.

4.5 Orientado a Objetos

C++ tenía que mantener las características y ser compatible con C. Cuando Java estaba siendo diseñado, sus diseñadores y desarrolladores no quisieron que Java fuera compatible al nivel de código fuente con ningún otro lenguaje. Por lo anterior, tuvieron la opción de crear un lenguaje orientado a objetos que hace uso de un modelo de objetos simple, y usa tipos de datos simples no objetos, asegurando un alto rendimiento.

4.6 Robusto

A medida que los usuarios de Java en Internet comenzaron a incrementarse en número, creció también la necesidad de ejecutar una aplicación en diversas plataformas. Estas plataformas diversas tenían demandas diferentes por parte de las aplicaciones para que se ejecutaran apropiadamente y por tanto, la aplicación tenía que ocuparse de todas estas demandas. Para poder hacer esto, la aplicación debía de ser robusta

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 10

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

El diseño de Java hace posible que los programadores identifiquen errores en la misma etapa de desarrollo. El código puede ser revisado para asegurar confiabilidad colocando restricciones en ciertas áreas claves de la programación y teniendo un diseño para evitar los errores más comunes de programación. Java está diseñado para ser un lenguaje estrictamente tipado, Por lo tanto, verifica errores de codificación tanto en tiempo de compilación como en tiempo de ejecución.

Java provee manejo de excepciones para ocuparse de los errores de una manera sofisticada. La robustez del manejo de excepciones de Java ayuda a construir programas confiables. Funciones como la recolección automática de basura en Java hace que los programas sean menos propensos a errores relacionados con la memoria. Esto a su vez da seguridad a los programadores para predecir el comportamiento del programa en diversas situaciones.

4.7 Dinámico

Java enlaza el código dinámicamente. Java fue implementado para usar los datos disponibles en los archivos class en tiempo de ejecución. Los objetos que se crean y usan en un programa son verificados y resueltos en tiempo de ejecución. Esta característica es útil cuando se quiere actualizar el bytecode en un sistema en ejecución.

4.8 Fuertemente Tipificado

Java es fuertemente tipificado. Java fue diseñado de forma que si se comete cualquier error en una invocación de método, se mostrará un mensaje de error al programador en tiempo de compilación. Por esta razón, los programadores no necesitan preocuparse de cometer errores no detectables en las invocaciones de métodos.

4.9 Interpretado

Los bytecodes de Java son interpretados por la JVM en el lenguaje nativo de la plataforma subyacente. Los lenguajes interpretados tienen limitaciones de rendimiento comparados con los lenguajes que son compilados. Java combina las ventajas de la compilación e interpretación. El compilador Java JIT puede ayudar a superar las limitaciones de rendimiento asociadas a la JVM.

4.10 Arquitectura Neutral

Al compilar un programa en Java, el código resultante es un tipo de código binario conocido como bytecode. Este código es interpretado por diferentes computadoras de igual manera, solamente hay que implementar un intérprete para cada plataforma. De esa manera Java logra ser un lenguaje que no depende de una arquitectura computacional definida.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 11

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

4.11 Ambiente Multihilos

Java brinda soporte a la programación multihilos, que permite que un único programa lleve a cabo varias tareas concurrentemente. Los programadores pueden hacer uso de esto para crear aplicaciones de red interactivas. El sistema en tiempo de ejecución de Java (JVM) se implementó de forma eficiente, para permitir la fácil sincronización de hilos, que a su vez facilitan la programación interactiva.

Ahora que se conocen las características principales de Java, se discute a continuación la plataforma de Java.

5. La Plataforma Java Una plataforma es el entorno sobre el cual se ejecutan los programas. Una plataforma puede ser una plataforma de software, una plataforma de hardware o una combinación de ambos. La plataforma Java es una plataforma de sólo software, la cual se puede ejecutar en varias plataformas de hardware así como en varios sistemas de operativos. La plataforma Java esta conformada por dos componentes, llamados la JVM y el API de Java, como se muestra en la Figura 1.4.

Figura 1.4: Los dos Componentes de la Plataforma Java

5.1 JVM

La JVM es una aplicación ejecutable que representa a un procesador genérico en el cual corren los bytecodes de Java. Una implementación particular de esta máquina virtual, que es escrita para operar en un entorno particular, aún brindará soporte al API general de Java. Esto es lo que hace a Java independiente de la plataforma.

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 12

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

La JVM consta de los siguientes tres aspectos:

• Especificación abstracta. • Implementación concreta. • Instancia en tiempo de ejecución.

Esto se muestra en la Figura 1.5.

Figura 1.5: Diferentes Aspectos de la JVM

La especificación Java define la especificación abstracta de la JVM, que se necesita para permitir que los programas se ejecuten en ella. La implementación concreta de la JVM es la implementación actual de la especificación abstracta. La instancia de tiempo de ejecución (la instancia de una JVM que está en ejecución actualmente) soporta la ejecución de los programas Java. El código fuente de Java (archivo .java) es convertido en bytecodes (archivo .class) por el compilador Java. Estos bytecodes son luego convertidos a código de máquina nativo por alguna JVM que sea específica a una plataforma en particular. De aquí que, los archivos .class son portables a cualquier implementación de la máquina virtual.

Para entender la diferencia entre los archivos .java y .class, se va a mostrar brevemente el flujo de un programa Java.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 13

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

• El código fuente Java se ingresa usando un editor. • El comando javac se usa para iniciar el compilador Java, que compila el código

fuente Java (archivo .java) a bytecodes, suponiendo que no hay errores en tiempo de compilación. Si existe un error, el programador debe regresar al editor, corregir los problemas, y ejecutar nuevamente javac hasta que todos los errores sean solucionados y se obtenga una compilación limpia.

• Una vez compilado, se produce un archivo .class que podrá ser usado con cualquier JVM ejecutándose en cualquier plataforma.

• El comando java se usa para iniciar el intérprete Java, y para ejecutar el archivo .class.

Se ha discutido que los bytecodes Java obtenidos después de la compilación en cualquier JVM pueden ser transferidos a cualquier otra JVM ejecutándose en cualquier otra plataforma y ser ejecutado allí. Esta característica ayudará a los usuarios a descargar bytecodes Java de la Internet y ejecutarlos en sus JVM sin riesgos de seguridad. Sin embargo, hay un pequeño problema, los bytecodes descargados no tienen que haber sido producidos por un compilador Java estándar, por lo que estos bytecodes pueden estar erróneos.

Para resolver este problema, una vez que el bytecode sea descargado, la JVM en la máquina del usuario inicia un proceso de verificación del bytecode. Durante este proceso, los fragmentos del bytecode son probados para verificar su validez. Se revisa cualquier manipulación ilegal de apuntadores, violación de restricciones colocadas para acceder a las variables y métodos de las clases, uso ilegal de objetos, etc. Si no se encuentran ninguna de las violaciones anteriores, y si el bytecode descargado pasa todas las otras pruebas que el verificador impone, entonces el bytecode es tratado como un código confiable.

Actualmente, el verificador de bytecode no realiza ninguna suposición acerca del bytecode que recibe. El bytecode puede provenir del sistema local o haber sido descargado de la Internet. Sin importar la fuente, el bytecode es objeto del mismo proceso de verificación; esto asegura la confiabilidad del código y también protege al intérprete Java. Dado que la confiabilidad del código fue verificada, el intérprete Java opera a toda capacidad sin tener que revisar cualquier aspecto de seguridad.

Cuando surge un aspecto vinculado con la seguridad en Java, el administrador de seguridad de Java juega un papel fundamental. El administrador de seguridad (clase java.lang.SecurityManager) es una clase definida en Java, que permite a las aplicaciones Java implementar una política apropiada de seguridad. Cuando una aplicación Java implementa esta política de seguridad, tiene la capacidad de determinar si la operación que está a punto de realizarse, es una operación insegura o sensible. También se pueden obtener más detalles de la operación, y si la operación se realiza dentro de un contexto de seguridad que permita a la aplicación llevar a cabo esa operación.

El modelo de seguridad de Java provee una ‘caja de arena’ (sandbox) que es configurable, ésta protege a las aplicaciones y applets Java de ser atacados por virus,

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 14

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

que son difundidos a través de programas descargados de máquinas no confiables. Las aplicaciones y applets Java pueden realizar cualquier operación que este bajo la supervisión de la caja de arena y nada más. En este modelo de caja de arena, las aplicaciones y applets Java pueden descargar cualquier código de cualquier máquina. El código no se revisa por virus, porque mientras se ejecuta el código, la caja de arena revisa si viene de una máquina confiable o no.

Si el código proviene de una máquina no confiable, se evita realizar cualquier operación que pueda dañar al sistema. La ventaja del modelo de caja de arena es que la aplicación Java no necesita revisar si el código es confiable, ni necesita revisar por virus en el código. La caja de arena evita que un virus o código no confiable realicen operaciones maliciosas.

La caja de arena de Java incluye las características de seguridad provistas por la JVM, el administrador de seguridad, el cargador de clases y el verificador de archivos class. La caja de arena se puede personalizar en dos de sus componentes, son estos: el administrador de seguridad y el cargador de clases. El administrador de seguridad puede ser personalizado al escribir clases definidas por el usuario. Las clases definidas por el usuario pueden ser creadas derivando de la clase java.lang.SecurityManager y sobrescribiendo los métodos necesarios. Estos administradores de seguridad personalizados son útiles cuando se quieren cargar clases que no son completamente confiables. No se tienen que escribir nuestra propia caja de arena personalizada para las aplicaciones y applets Java que se escriben día a día, simplemente se puede usar las cajas de arena estándar que otros crean. Si se quiere ejecutar un applet en un navegador Web, por ejemplo, se usa la caja de arena que viene con el navegador Web.

A continuación se discute el cargador de clases que es el otro componente que puede personalizarse de la caja de arena, El cargador de clases carga las clases en la JVM.

Los cargadores de clases pueden ser de dos tipos:

• Cargador de Clases Primordial. • Objetos Cargadores de Clases.

El cargador de clases primordial es actualmente una parte de la implementación de la JVM, mientras que el objeto cargador de clase es un objeto que se usa para cargar una clase. El cargador de clases primordial carga solamente clases confiables, incluyendo las clases definidas en el API Java que están disponibles en el sistema local. Es posible escribir objetos cargadores de clases propios, que pueden ser personalizados para cargar clases específicas. El cargador de clases primordial en principio no confía de las clases cargadas por estos objetos cargadores de clases. Actualmente, estos objetos cargadores de clases son sólo aplicaciones Java que se ejecutan en la JVM.

Considere una clase MiClase que es cargada por un objeto cargador de clases. Asuma que MiClase carga otras clases tales como OtraClase1 y OtraClase2. Estas dos clases son actualmente cargadas a través del mismo cargador de clases que ha cargado a MiClase.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 15

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

En Java, las clases son agrupadas dentro de paquetes, es decir, cada paquete tiene un conjunto de clases. El término espacio de nombres se refiere a la entidad que mantiene los nombres de las clases. Java usa paquetes para este propósito. Dentro de un espacio de nombres en particular, sólo puede existir una clase con un nombre dado. Sin embargo, puede existir cualquier número de cargadores de clases dentro de una JVM. Cada cargador de clases puede estar asociado a un espacio de nombre diferente. La misma clase puede ser cargada a través de diferentes cargadores de clases que están asociados a diferentes espacios de nombres. No puede haber ninguna interacción entre cargadores de clases que están presentes en diferentes espacios de nombres, a menos que el cargador de clase expresamente permita esa interacción.

Se pueden diferenciar las clases descargadas de la red desde diferentes máquinas en diferentes espacios de nombres. A estas clases se les restringirá el acceso a otra clase que esté en un nombre de espacios diferente. Así, se puede usar esta arquitectura de cargador de clase para evitar cualquier daño causado por código malicioso.

5.2 El API de Java

El API (Application Programming Interface) de Java es una muy buena colección de componentes de software apropiadas para el desarrollo de programas Java. En Java hay diferentes tipos de programas tales como aplicaciones, applets y Servlets. El API de Java ayuda al desarrollo y ejecución de estos diferentes tipos de programas mediante una amplia librería. El soporte de las diversas características de Java se realiza a través del API. Éstas son básicamente librerías o paquetes de componentes relacionados. La Figura 1.6 muestra las características provistas por el núcleo del API de Java.

Figura 1.6: Características Provistas por el Núcleo del API Java

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 16

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Se ha visto cómo Java evolucionó como una aplicación de Internet. A continuación se discute el impacto que Java ha tenido sobre Internet y la WWW.

6. Impacto de Java en la WWW Los usuarios de la WWW hacen uso de varios tipos de máquinas, y tienen diferentes plataformas. Así que el problema clave es hacer que la información en la Internet sea compatible con todas las plataformas. Debido a que Java permite la portabilidad, se logra este punto. Usando la característica de portabilidad, el mismo programa puede ser ejecutado en diferentes plataformas, con resultados predecibles. La información no necesita ser replicada para soportar diferentes plataformas.

El otro tema principal de los usuarios de la WWW enfrentan es la seguridad. Debido a la amplia difusión de los virus y programas que pueden capturar información como palabras claves y detalles de las tarjetas de crédito del sistema de archivos local, los usuarios hasta hace poco, estaban temerosos de descargar cualquier programa ejecutable desde máquinas no confiables.

Los programas Java no tienen permiso de acceder a cualquier recurso fuera del alcance de la JVM. Por esto, la JVM controla los intentos de romper la seguridad a través de programas Java.

Java también hace la programación de aplicaciones interactivas muy fácil, las cuales se usan en muchos portales en Internet para atraer clientes.

Java comenzó de una manera modesta al permitir que los programas se ejecutaran en la Internet usando los applets de Java. Sin embargo, esto ha crecido hasta alcanzar un mayor poder de funcionalidad. Existen varias tecnologías basadas en Java que se usan para obtener funcionalidades especializadas. Por ejemplo, tecnologías como los Java Servlets, Java Server Pages (JSP), Enterprise Java Beans (EJB), etc., han otorgado al programador mucho más poder para construir aplicaciones robustas y escalables para Internet.

Considere la Figura 1.7, la cual muestra como las diferentes tecnologías Java se usan para alcanzar varias funcionalidades en un ambiente Internet.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 17

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 1.7: Tecnologías Java en Internet

Nota: Todas las tecnologías listadas en la Figura 1.7, excepto la tecnología applet, están basadas en la ejecución sobre la JVM de una máquina en vez de la JVM de un navegador. Por lo tanto, sólo los applets tienen restricciones en acceder los recursos del sistema fuera de la JVM.

A continuación se estudian las diferentes clases y objetos en Java.

7. Clases y Objetos Una clase es un prototipo que se usa para definir las características y los comportamientos que son comunes a todos los objetos de un mismo tipo. Las variables se usan para representar las características de los objetos y los métodos se usan para representar el comportamiento de los objetos. Se puede declarar una variable especificando su tipo de datos y el nombre de la variable.

Similarmente, se puede declarar objetos especificando lo siguiente:

• Tipo (nombre de clase). • Nombre de Objeto.

int a;

Computador comp;

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 18

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

En el fragmento de código anterior, a es el nombre de la variable, e int es su tipo de datos. Similarmente, comp es el nombre del objeto, y Computador es el tipo del objeto, es decir, el nombre de la clase. Se pueden declarar muchas variables del mismo tipo de datos. Similarmente, se pueden declarar muchos objetos del mismo tipo (muchos objetos de la misma clase).

La Figura 1.8, muestra más de un objeto de una misma clase.

Figura 1.8: Clases y Objetos Java

La Figura 1.8 muestra una clase llamada Cliente y objetos con los nombres ObjetoA, ObjetoB y ObjetoC de este tipo. La clase Cliente es una representación orientada a objetos del cliente del mundo real, mantiene los datos del cliente. Típicamente, la clase tendrá variables miembro para mantener información, como el ID del cliente, el nombre del cliente, etc.

Se define una clase en Java usando la palabra reservada class. La sintaxis es la siguiente:

class NombreClase {

// variables miembro

// funciones miembro

}

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 19

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Considere la clase Computador, que tiene los atributos cpu, monitor, teclado y mouse. Se pueden crear dos instancias de la clase Computador que tengan diferentes valores para estos atributos. Estas dos instancias están representadas por comp1 y comp2.

Los objetos en Java se crean usando la palabra clave new.

La sintaxis es la siguiente:

NombreClase objecto = new NombreClase();

Los constructores en Java tienen la misma funcionalidad que en C++. Los constructores en Java pueden aceptar nombres de variables y tipos de variables como argumentos.

A su vez, como en C y C++, donde la función main() es el punto de inicio del programa, se tiene que main() es el punto de inicio del programa Java también.

La función main() tiene la siguiente declaración de función:

public static void main(String args[]){

// El código principal va aquí

}

Así como en C y C++, los programas Java pueden aceptar parámetros por la línea de comandos, el main()de Java puede tomar estos argumentos. En C o C++, se pueden tener parámetros de la línea de comandos usando int argc y char* argv[]. En Java, se toman como un arreglo de objetos String. Además, mientras en C o C++ es opcional para la función main() tomar argumentos desde la línea de comandos, es obligatorio que los argumentos de la línea de comandos estén declarados en la función main() de Java.

Nota: La función main() en Java no puede ser global, como en C o C++. En Java, debe estar presente dentro de una clase Java.

La palabra clave public es un tipo de especificador de acceso en Java. Se verán otros tipos de especificadores de acceso en el Volumen 2, Unidad 1 - Clases, Objetos y Referencias.

Las variables miembro son conocidos como miembros, y las funciones miembros como los métodos de una clase. No se puede tener la declaración de la clase separada, y la definición de la función miembro apareciendo libremente, como en C++. Ambos deben aparecer dentro del bloque de definición de la clase.

Observe el Ejemplo 1.1, que tiene el código Java para la clase Computador. En este momento, la sintaxis del código no es importante, dado que el punto ahora es entender la relación entre clases y objetos.

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 20

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Ejemplo 1. 1

El siguiente programa representa una computadora.

El código Java comienza aquí...

1. /*Definicion de la clase Computador comienza aqui*/

2. class Computador {

3. boolean cpu, teclado, mouse;

4. String monitor;

5. }/*Definicion de la clase Computador termina aqui*/

6.

7. /*Definicion de la clase ComputadorEjemplo comienza aqui*/

8. public class ComputadorEjemplo {

9. /*El metodo main comienza aqui */

10. public static void main(String[] args) { 11. //Crear la instancia de la clase Computer 12. Computador comp1 = new Computador(); 13. Computador comp2 = new Computador(); 14. 15. comp1.cpu = true; 16. comp1.monitor = "Negro"; 17. comp1.teclado = true; 18. comp1.mouse = true; 19. 20. comp2.cpu = true; 21. comp2.monitor = "Blanco y negro"; 22. comp2.teclado = true; 23. comp2.mouse = false; 24. }/* El metodo main termina aqui */ 25. }/*Definicion de la clase ComputadorEjemplo termina aqui*/

El código Java termina aquí

Fin del Ejemplo 1.1

Aquí, se tienen dos clases, Computador y ComputadorEjemplo. La clase Computador define el prototipo para un conjunto de objetos que tienen los mismos atributos. La clase ComputadorEjemplo crea dos objetos de tipo Computador, y

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 21

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

también se muestra que estos dos objetos pueden contener diferentes valores para sus atributos.

Considere la Figura 1.9 para entender mejor el código anterior.

Figura 1.9: Múltiples Objetos de una Clase

A continuación se discuten los principios de la programación orientada a objetos usados en Java.

8. Orientación a Objetos en Java Se sabe que Java brinda soporte a la programación orientada a objetos. En la programación orientada a objetos, los programadores crean objetos de software, que son modelados como los objetos del mundo real. Se describen los objetos del mundo real usando sus atributos y comportamiento. Similarmente se describen los objetos de software usando variables y métodos. Se tiene un prototipo a partir del cual se crean objetos del mismo tipo del mundo real. Similarmente, se tiene un prototipo llamado clase, de la cual se pueden crear muchos objetos de software del mismo tipo. Java implementa la orientación a objetos a través de tres importantes propiedades, que son:

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 22

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

• Encapsulación. • Herencia. • Polimorfismo.

A continuación se discuten en detalle cada uno de ellos.

8.1 Encapsulación

La capacidad de presentación de información dentro de un objeto se divide en dos partes bien diferenciadas:

• Interna: la información que necesita el objeto para operar y que es innecesaria para los demás objetos de la aplicación. Estos atributos se denominan privados y tienen como marco de aplicación únicamente a las operaciones asociadas al objeto.

• Externa La que necesitan el resto de los objetos para interactuar con el objeto que definimos. Estas propiedades se denominan públicas y corresponde a la información que necesitan conocer los restantes objetos de la aplicación respecto del objeto definido para poder operar.

Se puede imaginar la encapsulación como introducir el objeto dentro de una caja negra donde existen dos ranuras denominadas entrada y salida. Si se introducen datos por la entrada automáticamente obtendrá un resultado en la salida. No necesita conocer ningún detalle del funcionamiento interno de la caja.

El término encapsulación indica la capacidad que tienen los objetos de construir una cápsula a su alrededor, ocultando la información que contienen (aquella que es necesaria para su funcionamiento interno, pero innecesaria para los demás objetos) a las otras clases que componen la aplicación.

Esto se ilustra en la Figura 1.10.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 23

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 1.10: Encapsulación en una Clase

Esta característica está disponible en Java y se llama encapsulación.

Tome el ejemplo de un ATM, telecajero. Se puede ir a un ATM a retirar dinero, revisar el saldo de una cuenta, y depositar dinero. Estas son las funcionalidades proporcionadas a los usuarios. Ellos no saben cómo estas funcionalidades están implementadas, y no están preocupados por la implementación. Los usuarios pueden acceder a la información pertinente solo a sus cuentas. Ellos no pueden acceder a la información de otros usuarios, a los usuarios no se les da acceso a saber cómo trabaja el ATM.

Considere la Figura 1.11, que muestra como la encapsulación se lleva a cabo en una clase Java. La clase que se muestra es Direccion. Un objeto Direccion es instanciado y un método es invocado. El código que es privado en la clase Direccion no es visible para la clase ServicioCliente.

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 24

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 1.11: Encapsulación en el Objeto Direccion

8.2 Herencia

Considere el ejemplo de un profesor de física y uno de matemáticas. Ambos pertenecen a una categoría general llamada profesores. Ellos tienen ciertos atributos y comportamiento que son comunes a todos los profesores. Adicionalmente, ellos tienen ciertos atributos especiales que son comunes a todos los profesores de física y matemáticas. Cuando se modela este ejemplo usando objetos de software, se puede tener una clase llamada Profesor que defina todos los atributos y comportamiento comunes a todos los profesores. Subsecuentemente, se pueden definir dos clases ProfesorFisica y ProfesorMatematica, que hereden los atributos y comportamiento comunes a todos los profesores, desde la clase Profesor. En este caso, la clase Profesor será la súper clase de las clases ProfesorFisica y ProfesorMatematica y estas serán subclases de la clase Profesor.

Algunos lenguajes como C++, permiten la herencia múltiple en la cual una clase puede heredar de varias clases. En Java, una clase sólo puede tener una súper clase. Esto significa que una clase en Java no puede directamente derivar de varias clases. Sin embargo, Java soporta herencia múltiple indirectamente usando interfaces. Las interfaces serán tratadas en detalle en el Volumen 1, Unidad 5 – Clases Abstractas e Interfaces.

La Figura 1.12 muestra un ejemplo de herencia. De esta figura, se puede deducir que Bicicleta, MonoPatin y Moto tienen propiedades que son comunes a todos los

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 25

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

vehículos de dos ruedas, mientras que Carro, Autobus y Camion tienen propiedades que son comunes a todos los vehículos de cuatro ruedas. Además, los vehículos de dos y cuatro ruedas, a su vez, tienen propiedades que son comunes a los vehículos.

Figura 1.12: Herencia: Clases Como Especialización de la SuperClase Vehiculo

8.3 Polimorfismo

Se pueden tener muchas situaciones cuando se quieren hacer varias operaciones similares unas con otras dependiendo de la entrada que se obtenga. Esto se denomina polimorfismo, formado de dos raíces griegas, ‘poly’ y ‘morphus’. La palabra ‘poly’ significa muchos y 'morphus' significa formas.

En programación orientada a objetos, polimorfismo significa una sola interfaz y múltiples implementaciones. En otras palabras, los nombres de métodos son los mismos, pero tienen diferentes implementaciones basadas en los parámetros que le son pasados, o en los objetos sobre los cuales son invocados.

Suponga que se desea implementar a la clase Mamiferos, suponga también que uno de los métodos que se desea implementar para esta clase, es el que permita a tales mamíferos desplazarse de forma natural, a este método se le llamará desplazar(). Se encontrará entonces conque para algunos mamíferos el desplazamiento se realizará por medio de caminar, como es en el caso de las personas, para otros el desplazamiento natural será nadar, como en el caso de los delfines e inclusive para otros, el desplazamiento se logrará por medio de volar, como sucede con los murciélagos. Se usa el mismo nombre del método para invocar sus diferentes implementaciones.

Ahora, se va a comenzar la programación en Java escribiendo la aplicación HolaMundo, que escribe la cadena Hola Mundo en la salida estándar.

Los Ejemplos 1.2 y 1.3 tienen algunos elementos sintácticos, que no se han visto en detalle hasta ahora. Estos elementos serán cubiertos en las próximas unidades. Estos ejemplos simplemente ayudarán a exponer al usuario a la sintaxis Java.

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 26

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

9. Ejemplo de una Aplicación Java Observe el Ejemplo 1.2. La aplicación Java HolaMundo de este ejemplo imprime la cadena de caracteres Hola Mundo! en la salida estándar.

Ejemplo 1.2

El código Java comienza aquí...

1. /*Definicion de la clase HolaMundo comienza aqui*/ 2. public class HolaMundo { 3. /*El metodo main comienza aqui */ 4. public static void main(String[] args) { 5. System.out.println("Hola Mundo!"); 6. }/* El metodo main termina aqui */ 7. }/*Definicion de la clase HolaMundo termina aqui*/

El código Java termina aquí

En este programa, HolaMundo es el nombre de la clase, tienen un método (comparable a una función en C o a una función miembro en C++) con el nombre main. Este método tiene una instrucción que imprime Hola Mundo! en la salida estándar (el monitor) cuando se ejecuta. Esta clase define un prototipo, y se puede crear cualquier número de objetos de este tipo instanciando esta clase.

Ahora que se tiene el código fuente listo, se debe compilar el programa y ejecutarlo. El programa debe ser almacenado en un archivo bajo el nombre HolaMundo.java. Usualmente, el nombre del archivo será el mismo que el nombre de la clase que contiene el método main(), ya que la ejecución del programa usualmente comienza con el método main(). El archivo tendrá una extensión .java. Todo archivo Java puede tener solamente una clase, que sea public.

El próximo paso es compilar el programa para obtener los bytecodes (archivo .class). La compilación se realiza usando el comando javac, como sigue:

javac HolaMundo.java

Esto produce un archivo con el nombre HolaMundo.class, que contiene los bytecodes. Estos bytecodes son interpretados por el interprete Java, y entonces ejecutados. El intérprete Java se inicia usando el comando java, como se muestra a continuación:

java HolaMundo

La salida del programa en el monitor será:

Hola Mundo!

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 27

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Fin del Ejemplo 1.2

En la próxima sección, se presenta cómo escribir un applet Java que imprime la cadena de caracteres Hola Mundo!.

10. Ejemplo de Applet Java El applet Java HolaMundo que se presenta a continuación, imprime la cadena de caracteres Hola Mundo! en el área del applet.

Ejemplo 1.3

El código Java comienza aquí...

1. import java.applet.Applet;

2. import java.awt.Graphics;

3.

4. /*Definicion de la clase HolaMundo comienza aqui*/

5. public class HolaMundo extends Applet {

6. /*El metodo paint comienza aqui */

7. public void paint(Graphics g) {

8. // Llamar al metodo drawString

9. // del objeto Graphics

10. g.drawString("Hola Mundo!", 25, 25); 11. }/* El metodo paint termina aqui */ 12. }/*Definicion de la clase HolaMundo termina aqui*/

El código Java termina aquí

En este applet Java, primero se tienen las instrucciones import, que se usan para importar las clases Applet y Graphics. Estas son esenciales para un programa applet. Luego, se tiene la definición de la clase, con el nombre de la clase HolaMundo. Esta definición de la clase usa la palabra reservada extends, seguida del nombre de la clase Applet. Esto significa que la clase HolaMundo hereda sus características de la clase Applet. Se aprenderá más acerca de herencia en el Volumen 2, Unidad 3 -Herencia. Esta clase tiene un método con el nombre de paint, que imprime Hola Mundo!. La programación de Applets será discutida en el Volumen 6, Unidad 1 - Applets.

El código de este ejemplo también muestra el uso de los comentarios en Java. Hay básicamente tres tipos de comentarios que se usan en Java. Son los siguientes:

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 28

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Comentarios de Documentación: Encerrados dentro de /** … */. Estos comentarios se usan para generar documentación en las clases en Java.

Bloques de Comentarios: Encerrados dentro de /* */. Estos comentarios se usan típicamente antes de un método o clase para describir su funcionalidad.

Comentarios de Implementación: Comienzan con //. Estos comentarios se usan típicamente dentro de la implementación del método para explicar una expresión o una lógica de implementación compleja.

Se necesita escribir un archivo HTML para visualizar este applet. El código para el archivo HTML requerido para ejecutar el applet HolaMundo se muestra a continuación:

El código HTML comienza aquí...

<html>

<head>

<title>Hola Mundo</title>

<body>

<applet code="HolaMundo.class" width=200 height=50>

</applet>

</body>

</html>

El código HTML termina aquí

El parámetro incluido en la etiqueta <applet> se usa para invocar el archivo HolaMundo.class, y ejecutarlo. Este archivo se llamará HolaMundo.html. Se necesita tener ambos el applet(archivo .class) y el archivo HTML en el mismo directorio, una vez hecho esto, se puede ejecutar el applet usando el siguiente comando:

appletviewer HolaMundo.html

La ventana del visualizador de applet se abre, y la salida del applet será la siguiente:

Hola Mundo!

Fin del Ejemplo 1.3

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 29

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Resumen Ahora, que ha completado esta unidad, usted debe ser capaz de:

• Discutir la evolución de Java. • Comparar Java con C++. • Mencionar las principales características de Java. • Explicar la plataforma Java. • Describir el impacto de Java en la WWW. • Definir clases y objetos. • Explicar los principios de orientación a objetos en Java.

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 30

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 1: Examen de Autoevaluación 1) ¿Cuál de los siguientes lenguajes visualiza los componentes del programa como

objetos? a) Lenguaje Procedimental b) Lenguaje Orientado a Objetos c) Lenguaje de Máquina d) Ninguno de los anteriores

2) ¿Cuál de las siguientes características describe la arquitectura del lenguaje Java?

a) Orientado a Procedimientos b) Abstracto c) Independiente de Plataforma d) Específico

3) ¿Cuál método deben tener todos los programas de aplicación Java?

a) start()

b) begin()

c) main()

d) main(String args[])

4) ¿Cuál es el comando para ejecutar un programa compilado en Java? a) javac

b) java

c) run

d) execute

5) En Java, una clase puede tener cualquier número de súper clases. a) Verdadero b) Falso

6) ¿Cuáles de los siguientes programas puede acceder a recursos fuera de la JVM?

a) Aplicaciones Java b) Applets Java c) Servlets Java d) Ninguno de los anteriores

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 31

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

7) ¿Cuál es la extensión usada para guardar los archivos fuente Java? a) .java

b) .javac

c) .javax

d) .src

8) ¿Cuál de los siguientes es usado para referirse a una subclase? a) Clase Interna b) Clase Anidada c) Clase Derivada d) Clase Oculta

9) ¿Cuál de las siguientes opciones ha hecho popular a Java a través de la Internet?

a) Applets Java b) Aplicaciones Java c) Bytecodes Java d) Ninguna de las anteriores

10) ¿Cuál de las siguientes afirmaciones es cierta acerca de Java?

a) Tiene solo un compilador b) Tiene solo un interpretador c) Tiene ambos un compilador y un interpretador d) Interpreta y luego compila

Core Java Guía del Estudiante

Unidad 1: Visión General de Java Libro 1: Core Java 32

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Respuestas a la Unidad 1: Examen de Autoevaluación 1) b 2) c 3) d 4) b 5) b 6) a y c 7) a 8) c 9) a

10) c

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 33

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 2: Operadores, Expresiones y Control de Flujo

Objetivos del Aprendizaje Al final de esta unidad, usted será capaz de:

• Mencionar los tipos de datos primitivos usados en Java. • Describir la declaración e inicialización de variables en Java. • Discutir los diferentes operadores usados en Java. • Explicar la precedencia de operadores en Java. • Definir los tipos de conversiones automáticas y explícitas en Java. • Explicar las diferentes estructuras de control usadas en Java.

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 34

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

1. Introducción En esta unidad, se discute la sintaxis básica de Java, se encontrarán muchas similitudes entre la sintaxis de Java y C++.

Antes de aprender acerca de la sintaxis de programación de Java, se discuten los tipos de datos que provee el lenguaje Java.

2. Tipos de Datos en Java Los tipos de datos en Java son de dos tipos:

• Tipos Primitivos: Tipos de datos que mantienen valores primitivos como 10, ‘a’, 12.2 etc.

• Tipos Referencias: Tipos de datos que mantienen valores de referencia como objetos y arreglo de referencias.

Además de los tipos de datos en Java, también existen los genéricos que nos permiten especificar el tipo de elemento de un Colección en tiempo de compilación. En lugar de especificar una lista, especificamos su contenido, por ejemplo: Double (doble).

La Figura 2.1 muestra los tipos de datos que Java soporta.

Figura 2.1: Tipos de Datos en Java

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 35

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

En la Figura 2.1, bajo los tipos primitivos, se tienen ocho tipos de datos. Los nombres mostrados en la figura son las palabras claves usadas en Java para denotar estos tipos de datos. Los tres tipos referencia, es decir, arreglos, clases e interfaz, se les coloca identificadores definidos por el usuario al escribir código Java. Por ejemplo, nombre[20] denota a nombre definido por el usuario como tipo arreglo.

A continuación se verá en detalle los tipos de datos primitivos usados en Java.

2.1 Tipos Primitivos

Los tipos de datos primitivos se usan para definir variables en Java. El tipo de dato especificado junto con un identificador en el momento de la declaración de la variable define el rango de valores que puede ser almacenado en esta variable. Java provee ocho tipos de datos primitivos. La Tabla 2.1 proporciona el nombre del tipo de dato primitivo y el tamaño ocupado por cada tipo de dato primitivo en memoria.

Tipo de Dato Primitivo Tamaño Ocupado en Memoria

boolean 1 byte

byte 1 byte

char 2 bytes

short 2 bytes

int 4 bytes

Long 8 bytes

Float 4 bytes

Double 8 bytes

Tabla 2.1: Tamaño Ocupado por los Tipos de Datos Primitivos en la Memoria

A continuación se discute cada uno de los ocho tipos de datos en Java, comenzando con los tipos de datos enteros.

2.1.1 Tipos de Datos Enteros Los tipos de datos enteros se usan para almacenar valores enteros. La Figura 2.1 muestra cinco tipos diferentes de tipos de datos enteros, estos son: byte, short, int, long, y char. El rango de valores que estos tipos de datos primitivos pueden almacenar se muestra a continuación:

• byte -27 hasta 27 – 1 • short -215 hasta 215 – 1

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 36

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

• int -231 hasta 231 – 1 • long -263 hasta 263 – 1

Las diferentes variables de los tipos de datos enteros se declaran como se muestra en el siguiente código:

byte b = 1;

short s = 1;

int i = 1;

long l = 1;

En las declaraciones anteriores, a todas las variables se les ha asignado el valor del literal entero 1. Los literales son valores constantes que son asignados a las variables.

El tipo de dato char se usa para almacenar caracteres. Estos caracteres deben ser caracteres Unicode. Unicode provee números únicos a los caracteres, que permanecen igual en cualquier plataforma o lenguaje.

Debido a que se usan números para almacenar caracteres en la máquina, el tipo de datos char esta dentro de la categoría de tipos de datos enteros.

El rango del tipo de datos char se muestra a continuación:

char 0 hasta 215

Java reserva 2 bytes para almacenar el valor de un char. El siguiente código muestra la declaración de una variable char.

char ch = ‘a’;

Los literales de carácter se definen usando la comilla simple, mientras que las cadenas de caracteres se definen usando comillas dobles. Java también usa secuencias de escape, en los caracteres. Una secuencia de escape es un conjunto especial de caracteres que tienen algún significado especial. Todas las secuencias de escape en Java comienzan con el caracter ‘\’. A continuación se muestran algunas secuencias de escape en Java:

• \r – retorno de carro • \n – nueva línea • \t – tabulador • \b – borrado a la izquierda • \f – comienzo de página • \\ - caracter \ • \’ – comilla simple ’ • \" – comilla doble ”

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 37

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Un programa Java puede interactuar con caracteres internacionales, lo cual no es posible en C o C++, a menos que se programen cada conjunto de caracteres separadamente.

2.1.2 Tipos de Datos de Punto Flotante Los tipos de datos de punto flotante se usan para almacenar valores de punto flotante. Los dos tipos de tipos de datos para punto flotante son float y double.

El rango de estos tipos de datos primitivos es el siguiente:

float -3.4 * 1038 hasta 3.4 * 1038 double -1.8 * 10308 hasta 1.8 * 10308

El siguiente código muestra la declaración de dos variables pertenecientes al tipo de datos de punto flotante.

float a = 1.1f;

double d = 1.1;

Las variables literales float deben terminar con f o F.

La Figura 2.2 muestra literales que se pueden asignar a float y double.

Figura 2.2: Literales Asignados a float y double

2.1.3 Tipo de Datos boolean El tipo de datos boolean se usa para almacenar valores booleanos, es decir, true o false. La palabra clave boolean se usa para denotar el tipo de datos booleano. El siguiente código muestra la declaración de una variable boolean.

boolean bool = true;

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 38

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

2.1.4 Valores Aceptables Para Diferentes Tipos de Datos Primitivos en Java La Tabla 2.2 muestra algunos ejemplos de valores aceptables para los diferentes tipos de datos primitivos en Java.

Tipo de Datos Valor Aceptable

Entero

2 (se asume int) 2L 0777 (octal) 0xa5fd (hexadecimal) ‘a’, ‘\n’, ‘\udddd’

Punto Flotante

3.14 (se asume double) 3.12E4 2e12 2.0d 2.0F

Boolean true, false

Tabla 2.2: Algunos Ejemplos de Valores para los Tipos de Datos en Java

2.1.5 Tamaños de los Tipos de Datos en C, C++, y Java En lenguajes como C y C++, el tamaño del tipo de datos puede variar entre plataformas y es dependiente de la máquina. Por ejemplo, el tipo de datos entero ocupa 2 bytes en ciertos compiladores de C, en cambio ocupa 4 bytes en otros.

En Java, sin embargo, el tamaño del tipo de datos es independiente de la plataforma en la cual la aplicación se ejecuta. El tamaño de cada tipo de datos primitivo es el mismo sin importar la plataforma. Por ejemplo, el tipo de datos entero siempre ocupa 4 bytes en cualquier implementación válida de la JVM. Un valor por defecto está siempre asociado con los tipos de datos primitivos. Para los tipos de datos enteros, el valor por defecto es 0. Para los tipos de datos de punto flotante, el valor por defecto es siempre 0.0. Para los tipos de datos caracteres, el valor por defecto es \u0000. El valor por defecto para los boolean es false.

2.2 Tipos de Referencia

Los tres tipos de referencia provistos por Java son los arreglos, clases e interfaz. No se entrará en una discusión detallada de estos tres tipos de datos ahora, solo se mencionará que una referencia es un elemento de datos que mantiene la dirección de una posición de memoria. Los arreglos en Java no son referidos como tipos de datos estructurados como en C o C++. Los arreglos son tipos referencia, donde el identificador que se usa para identificar al arreglo contiene la dirección del arreglo. Estos serán tratados en detalle en una sección posterior en esta unidad.

Java es un lenguaje de programación orientado a objetos, y por esto todo el esfuerzo en la programación esta alrededor de la creación de clases. Java también permite la creación de interfaces, que son similares a las clases. Los identificadores usados para

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 39

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

identificar a las clases e interfaces mantienen la dirección de la posición de la memoria. Las clases son analizadas en detalle en el Volumen 2, Unidad 1 – Clases, Objetos y Referencias y las interfaces en el Volumen 2, Unidad 5 – Clases Abstractas e Interfaces. A continuación se muestra una breve descripción sobre los genéricos.

2.3 Genéricos

Java 5.0 introduce nuevas funcionalidades al lenguaje de programación Java. Una de esas funcionalidades son los genéricos. Puede que usted encuentre construcciones similares en otros lenguajes pero verá que hay diferencias importantes entre ellas. Los genéricos le permiten hacer abstracciones de tipos de datos. Estos serán tratados en detalle en el Volumen 8 - Conceptos Avanzados, Unidad 1 – API de Colecciones.

Seguidamente, se va a aprender acerca de clases envolventes (wrapper classes), que esencialmente envuelven los tipos de datos primitivos en clases.

3. Clases Envolventes Se han discutido varios tipos de datos primitivos de Java. Java también provee clases envolventes para cada uno de estos tipos de datos primitivos. Una clase envolvente da la funcionalidad de una clase para un tipo de datos primitivo. Estas clases envolventes tienen métodos que permiten manipular el tipo de dato primitivo correspondiente que ellos envuelven.

Los tipos de datos primitivos tienen conjuntos de operaciones que se pueden usar con ellos. Sin embargo, cuando se quiere proveer algunas funciones utilitarias para un tipo de dato en particular, se usan las clases envolventes y se proveen funciones primitivas dentro de las clases envolventes.

Hay ciertas clases, que vienen como parte de la librería de Java, que requieren de un objeto en vez de una variable de tipo de dato primitivo. Los objetos de las clases envolventes se pueden usar también para este propósito.

Java provee clases envolventes para los ocho tipos de datos primitivos. Se discute a continuación las ocho clases envolventes en Java, comenzando por la clase envolvente Boolean.

3.1 La Clase java.lang.Boolean

La clase Boolean es la representación en objeto del tipo de dato primitivo boolean. Esta clase, es una clase envolvente para el tipo primitivo boolean, por lo tanto, tiene un miembro del tipo boolean. También tiene ciertos métodos que se pueden usar para manipular el valor del boolean almacenado internamente.

La clase Boolean tiene el método booleanValue(), que retorna el valor del boolean que está envuelto en este objeto. También tiene los métodos equals(), toString() y hashCode() que son sobrescritos de la clase java.lang.Object.

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 40

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

La clase Boolean tiene el método static valueOf() para convertir una representación de objeto String en un valor Boolean.

3.2 La Clase java.lang.Byte

La clase Byte es la representación en objeto del tipo de dato primitivo byte. Esta clase, por ser una clase envolvente para el tipo de dato primitivo byte, tiene un miembro del tipo byte. Esta clase tiene métodos que permiten obtener el valor del byte almacenado en el objeto Byte en la forma de byte, short, int, float o double. Esto se hace usando los siguientes métodos:

• byteValue() • shortValue() • intValue() • floatValue() • doubleValue()

La clase Byte también tiene métodos que son sobrescritos de la clase java.lang.Object. Estos métodos son los siguientes:

• equals() • toString() • hashCode()

Además de estos métodos, la clase Byte tiene el método static valueOf() para convertir una representación de objeto String en un valor byte.

3.3 La Clase java.lang.Short

La clase Short es la representación en objeto del tipo de dato primitivo short. Esta clase, por ser una clase envolvente para el tipo primitivo short, tiene un miembro del tipo short. Esta clase tiene métodos que permiten obtener el valor del short almacenado en el objeto Short en la forma de byte, short, int, float o double. Esto se hace usando los métodos:

• byteValue() • shortValue() • intValue() • floatValue() • doubleValue()

La clase Short también tiene los métodos equals(), toString() y hashCode() que son sobrescritos de la clase java.lang.Object.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 41

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

La clase Short tiene el método static valueOf() para convertir una representación del objeto String en un valor Short.

3.4 La Clase java.lang.Character

La clase Character es la representación en objeto del tipo de dato primitivo char. La clase Character, al ser una clase envolvente, tiene un campo del tipo primitivo char. Se pueden usar los métodos provistos por esta clase para manipular variables que mantienen valores del tipo primitivo char. Algunas de las funciones importantes provistas por esta clase dan la posibilidad de determinar el tipo de carácter y convertir un carácter en minúscula a mayúscula y viceversa. Los métodos definidos en la clase Character están basados en la tabla de atributos Unicode. Esta tabla asocia a cada código Unicode definido con un nombre. Los caracteres están encerrados dentro de comillas simples. Así, ‘a’ es el carácter a. Se pueden obtener caracteres especiales usando secuencias de escape. ‘\n’ es la secuencia de escape para el carácter de nueva línea.

Se puede usar el método charValue() de esta clase para obtener el valor char almacenado por el objeto en la forma del tipo de dato primitivo char.

3.5 La Clase java.lang.Integer

La clase Integer es la representación en objeto del tipo de dato primitivo int. Un objeto Integer tiene un campo, que es del tipo primitivo int. Es posible usar los métodos provistos por esta clase para manipular variables que mantienen valores del tipo primitivo int.

Algunas de las funciones más importantes provistas por esta clase son la posibilidad de convertir un int a un String con el método toString(), y de un String a un int usando el método parseInt(String s). Cuando la JVM encuentra valores int en el código, los interpretará como enteros. Cuando se usa un número como 2, la JVM asume que es del tipo int. Si se quiere que la JVM lo interprete como algo diferente a un int, se debe proveer información más específica. Si se quiere que la JVM “piense” que es del tipo long, se debe usar una "L" después del entero. Los otros tipos de datos enteros byte y short no pueden ser especificados. Estos serán convertidos al momento de la asignación de valores. Así, la sentencia byte b = 120; convertirá 120 de int a byte, siempre y cuando el valor pertenezca al rango válido para un byte.

Esta clase tiene métodos que permiten obtener el valor del int almacenado en el objeto Integer en la forma de byte, short, int, float o double usando los métodos byteValue(), shortValue(), intValue(), floatValue() y doubleValue() respectivamente.

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 42

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

3.6 La Clase java.lang.Long

La clase Long es la representación en objeto del tipo de dato primitivo long. Esta clase, por ser una clase envolvente del tipo primitivo long, tiene un miembro del tipo long. Esta clase tiene métodos que permiten obtener el valor del long almacenado en el objeto Long en la forma de byte, short, int, float o double usando los métodos byteValue(), longValue(), intValue(), floatValue() y doubleValue() respectivamente. La clase Long tiene también los métodos equals(), toString() y hashCode() que son sobrescritos desde la clase java.lang.Object.

La clase Long tiene un método static valueOf() para convertir una representación del objeto String en un valor Long.

3.7 La Clase java.lang.Float

La clase Float es la representación en objeto del tipo de dato primitivo float. Esta clase, por ser una clase envolvente del tipo primitivo float, tiene un miembro del tipo float. También tiene métodos que permiten obtener el valor del float almacenado en el objeto Float en la forma de byte, short, int, float o double usando los métodos byteValue(), shortValue(), intValue(), floatValue(), longValue() y doubleValue() respectivamente.

La clase Float también tiene los métodos equals(), toString() y hashCode() que son sobrescritos de la clase java.lang.Object.

La clase Float tiene el método static valueOf() para convertir una representación del objeto String en un valor Float.

3.8 La Clase java.lang.Double

La clase Double es la representación en objeto del tipo de dato primitivo double. Esta clase, por ser una clase envolvente para el tipo primitivo double, tiene un miembro del tipo double. También tiene métodos que nos permiten obtener el valor del double almacenado en el objeto Double en la forma de byte, short, int, float o double usando los métodos byteValue(), shortValue(), intValue(), floatValue() y doubleValue() respectivamente.

La clase Double también tiene los métodos equals(), toString() y hashCode() que son sobrescritos de la clase java.lang.Object, así como el método static valueOf() para convertir una representación del objeto String en un valor Double.

Considere el Ejemplo 2.1, que muestra el uso de las clases envolventes en Java.

Ejemplo 2.1

El código Java comienza aquí...

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 43

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

1. /*Definicion de la clase EnvolventesEjemplo comienza aqui*/ 2. public class EnvolventesEjemplo { 3. /*El metodo main comienza aqui */ 4. public static void main(String args[]) { 5. Integer i = new Integer(5); 6. String s = "250.47"; 7. 8. System.out.println("Valor de i es: " 9. + i.toString()); 10. System.out.println("Valor de s es: "

11. + Float.parseFloat(s));

12.

13. Float f = Float.valueOf(s);

14. float primitivoFloat = f.floatValue();

15. int primitivoInt = f.intValue();

16.

17. System.out.println("Valor del primitivo float es: "

18. + primitivoFloat);

19. System.out.println("Valor del primitivo int es: "

20. + primitivoInt);

21. }/* El metodo main termina aqui */

22. }/*Definicion de la clase EnvolventesEjemplo termina aqui*/

El código Java termina aquí

El código anterior usa varios métodos estáticos y métodos de instancia en las clases envolventes. El programa muestra el uso de las clases envolventes para Integer y Float. La salida del código anterior es la siguiente:

Valor de i es: 5

Valor de s es: 250.47

Valor del primitivo float es: 250.47

Valor del primitivo int es: 250

Fin del Ejemplo 2.1

Existen otras dos clases en Java, una de ellas se ocupa de los enteros de precisión arbitraria inmutables, y la otra de números decimales con signo de precisión arbitraria inmutables. La primera clase esta representada por java.math.BigInteger y la segunda clase por java.math.BigDecimal. Dado, que ambas clases tratan también con números en Java, se van a discutir acerca de ellas brevemente.

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 44

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

4. Math Clases Colaboradoras sobre los Tipos de Datos Java provee un número de paquetes. Los paquetes son contenedores para las clases, los cuales serán tratados en detalle en el Volumen 2, Unidad 7 – Paquetes. Los tipos primitivos enteros de Java no pueden efectuar operaciones sobre números largos, por esto Java provee un paquete llamado Math, que tiene dos clases, son estas: BigInteger y BigDecimal, para realizar operaciones matemáticas sobre números largos. Se aprenderá a continuación acerca de estas dos clases, BigInteger y BigDecimal.

4.1 La Clase java.math.BigInteger

Esta clase provee la abstracción de enteros de un ‘tamaño de palabra infinito’ representados por el tipo de datos int. Esta clase es inmutable, lo que significa que el valor representado por esta clase no puede cambiar; representa enteros de precisión arbitraria. BigInteger se representa usando la forma de complemento a dos, como en el caso del tipo de dato primitivo int. Todos los operadores que se pueden usar con el tipo de dato primitivo entero tienen operadores análogos que se pueden usar con BigInteger. Usando BigInteger, se pueden realizar manipulaciones de bits, verificar si un número es primo, generar un número de primo, calcular el Máximo Común Divisor, etc.

4.2 La Clase java.math.BigDecimal

Esta clase se usa para representar dígitos a la derecha del punto decimal en una escala de un entero de 32-bit. BigDecimal usa un valor sin escala que es entero de precisión arbitraria. Esta clase provee métodos que permiten realizar operaciones aritméticas básicas y manipulaciones de escala, también ayuda a comparar dos valores BigDecimal y a convertir el formato de los valores BigDecimal. La clase BigDecimal también permite especificar el comportamiento del redondeo para los valores decimales proporcionando ocho modos de redondeo.

En C o C++, se usan arreglos de caracteres para representar cadenas de caracteres (strings). Java, por el contrario, provee la clase String, que se puede usar para almacenar y manipular cadenas de caracteres. Se va a examinar el manejo y manipulación de String.

5. Manejo de String El manejo de cadenas de caracteres (string) en Java se hace usando las clases String o StringBuffer, ambas clases se usan para almacenar y manipular cadenas de caracteres. Sin embargo, hay una diferencia principal entre estas dos clases en la forma en la que son manejados por el sistema de tiempo de ejecución de Java. Se va a profundizar en estas dos clases para entender la diferencia.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 45

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

5.1 La Clase String

El literal string se usa para almacenar valores string (cadena de caracteres). La clase String se usa para denotar un literal string. Se puede especificar strings al encerrar el texto dentro de comillas dobles, es importante notar la diferencia entre comillas simples y dobles: ‘z’ no es equivalente a “z”. La primera es el carácter z, la segunda es una cadena de caracteres (string) de un carácter. El siguiente código muestra la declaración de una variable String.

String str = "Hola";

El fin de una cadena de caracteres es usualmente indicado por ‘\0’.

La clase String es inmutable, lo que significa que su valor no puede ser cambiado una vez que se crea un objeto del tipo String.

Se pueden usar métodos definidos en la clase String para hacer lo siguiente:

• Examinar los diferentes caracteres que componen una cadena de caracteres. • Buscar una sub-cadena dentro de una cadena de caracteres. • Comparar dos cadenas de caracteres. • Crear otra cadena de caracteres que tenga todos los caracteres de la primera

cadena de caracteres en mayúsculas o minúsculas.

Dos cadenas de caracteres pueden ser concatenadas usando el operador "+" como se muestra en la Figura 2.3. Como String es inmutable, esta concatenación es actualmente implementada usando internamente la clase StringBuffer por Java. En la próxima sección, se discute la clase StringBuffer.

String uno = "abcde";

String dos = "fghij";

String tres;

tres = uno + dos;

System.out.println(tres);

Figura 2.3: Uso de la Clase String

El objeto tres es creado y tiene el valor abcdefghij.

5.1.1 El paquete java.util.regex

Este paquete está constituido por dos clases: la clase Matcher y la clase Pattern y por una excepción, PatternSyntaxException. Las clases son usadas para hacer corresponder secuencias de caracteres con patrones especificados por expresiones regulares.

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 46

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Una instancia de la clase Pattern representa una expresión regular que es especificada en forma de secuencias de caracteres con una sintaxis similar a la usada por Perl.

Las instancias de la clase Matcher son usadas para hacer corresponder secuencias de caracteres con un patrón dado. La entrada (Input) es proporcionada a las clases Matcher a través de la interface CharSequence con el fin de soportar la correspondencia con caracteres procedentes de una amplia variedad de fuentes de entrada (archivos, string, etc).

5.1.2 Las clases Pattern y Matcher La clase Pattern:

Es una representación compilada de una expresión regular, es decir, representa la expresión regular que necesita ser compilada. Pertenece al paquete java.util.regex.

La clase Pattern implementa la interfaz Serializable. Para crear una instancia de la clase Pattern, se puede compilar una expresión regular, especificada como una cadena de caracteres (String). El patrón resultante luego puede ser usado para crear un objeto Matcher que puede hacer corresponder secuencias de caracteres arbitrarios con la expresión regular. Todo el estado involucrado en la realización de una correspondencia (match) reside en el objeto. Por lo tanto, muchos objetos Matcher pueden compartir el mismo patrón.

Una secuencia de invocación típica es:

Pattern p = Pattern.compile("a*b");

Matcher m = p.matcher("aaaaab");

boolean b = m.matches();

El método matches esta definido por esta clase como un recurso para cuando una expresión regular sea usada sólo una vez. Este método compila una expresión y hace la correspondencia (match) de una secuencia de entrada con ésta, en una invocación sencilla.

La siguiente sentencia boolean b = Pattern.matches("a*b", "aaaaab");

es equivalente a las tres sentencias anteriores aunque para correspondencias repetidas es menos eficiente ya que no permite que el patrón compilado sea reutilizado.

Las instancias de la clase Pattern son inmutables y seguras para ser usadas por múltiples hilos concurrentes. Las instancias de la clase Matcher no son seguras para tal uso.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 47

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

La clase Matcher:

La clase Matcher implementa MatchResult.

Esta clase es un motor que realiza operaciones de correspondencia sobre una secuencia de caracteres interpretando un patrón.

Una instancia de la clase Matcher es creada a partir de un patrón mediante la invocación del método matcher de la clase Pattern. Una vez creada, una clase Matcher puede ser usada para realizar tres tipos diferentes de operaciones de correspondencia:

• El método matches intenta hacer corresponder la secuencia de entrada completa con el patrón.

Si la correspondencia tiene éxito, entonces se puede obtener más información por intermedio de los métodos start, end, y group. Este método retorna verdadero si y sólo si la secuencia de entrada completa se corresponde con este patrón de Matcher.

• El método lookingAt intenta hacer corresponder la secuencia de entrada, comenzando desde el principio de la región, con el patrón.

Como el método matches, este método siempre comienza al principio de la región. La diferencia de ese método es que no requiere que el patrón completo sea correspondido. Si la correspondencia tiene éxito entonces se puede obtener más información por medio de los métodos start, end, y group. Este método retorna verdadero si y sólo si la secuencia de entrada se corresponde con este patrón de Matcher. • El método find, intenta encontrar la próxima subsecuencia de la secuencia de

entrada que se corresponde con el patrón. Este método comienza al principio de la región de la clase Matcher, o si una invocación anterior del método fue exitosa y el matcher no ha sido reestablecido (reset) desde entonces, en el primer caracter no correspondido por la anterior correspondencia. Si la correspondencia tiene éxito, entonces se puede obtener más información por intermedio de los métodos start, end, y group. Este método retorna verdadero si y sólo si una subsecuencia de la secuencia de entrada se corresponde con el patrón de este Matcher.

Cada uno de estos métodos retorna un boolean indicando éxito o fracaso. Se puede obtener más información acerca de una correspondencia exitosa haciendo una consulta del estado del matcher.

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 48

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Una clase Matcher encuentra correspondencias en un subconjunto de su entrada (input) llamado la región. Por defecto, la región contiene toda la entrada de Matcher. La región puede ser modificada por intermedio del método region y consultada a través de los métodos regionStart and regionEnd. La forma en que los límites de la región interactúan con algunos constructores de patrones puede ser cambiada. Ver useAnchoringBounds y useTransparentBounds para más detalles.

La clase Matcher también define métodos para reemplazar subsecuencias correspondidas con nuevas cadenas de caracteres cuyos contenidos pueden ser, si se desea, computados a partir del resultado de la correspondecia. Los métodos appendReplacement y appendTail pueden ser usados sucesivamente para recoger el resultado dentro de un buffer de cadena de caracteres existente, o el método replaceAll más conveniente puede ser usado para crear una cadena de caracteres en la cual cada subsecuencia correspondida en la secuencia de entrada es reemplazada.

El estado explícito de una clase Matcher incluye los índices de inicio y culminación de la correspondencia exitosa más reciente. También incluye los índices de inicio y culminación de la subsecuencia de entrada capturada por cada grupo de captura en el patrón así como un conteo total de tales subsecuencias. Como una conveniencia, también se proveen métodos para retornar estas subsecuencias capturadas en forma de caracteres de cadena.

El estado explícito de una clase Matcher inicialmente no está definido. Si se intenta hacer una consulta de cualquier parte de éste antes de una correspondencia exitosa esto causará que una IllegalStateException sea lanzada. El estado explícito de una clase Matcher es computarizada de nuevo por cada operación de correspondencia.

El estado implícito de una clase Matcher incluye la secuencia de caracteres de entrada así como la posición append, la cual es inicialmente cero y es actualizada por el método appendReplacement.

Es posible que una clase Matcher sea reestablecida explícitamente al invocar su método reset() o, si se desea una nueva secuencia de entrada, su método reset(CharSequence). Cuando se reestablece una clase Matcher, se elimina la información de su estado explícito y se establece la posición append en cero.

Las instancias de esta clase no deben ser usadas por múltiples hilos concurrentes, ya que no son seguras.

5.2 La Clase StringBuffer

La clase StringBuffer es similar a la clase String y se usa para denotar a un literal string. Sin embargo, StringBuffer es mutable, a diferencia de la clase String. Esto significa que los valores almacenados por objetos de esta clase pueden ser cambiados. StringBuffer juega un rol vital en la concatenación de cadenas de caracteres, actualmente se implementa a través de la creación de objetos StringBuffer, y luego

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 49

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

se usa el método append() sobre los objetos creados. Esto es una alternativa mejor que usar el operador + sobre dos objetos String.

Los objetos StringBuffer se pueden usar en aplicaciones multihilos, ya que los métodos que operan en estos objetos pueden ser sincronizados para evitar la ocurrencia del interbloqueo. Se aprenderá acerca de los interbloqueos en detalle en el Volumen 7, Unidad 3 – Sincronización de Hilos.

Se han discutido varios tipos de datos soportados por Java, los cuales representan varios tipos de valores que se pueden usar en programas Java. Estos valores son almacenados usualmente en la memoria de la pila, y se pueden cambiar cualquier número de veces dentro de un mismo programa Java. Los nombres de las variables o identificadores se usan para localizar estos valores. A continuación se discuten los nombres de variables o identificadores.

5.3 La Clase StringBuilder

Esta clase proporciona un API compatible de StringBuffer, pero no se garantiza su uso bajo escenarios de sincronización. Fue diseñada para usarla como el reemplazo de StringBuffer en donde el string sea utilizado por un solo hilo (generalmente es el caso). En lo posible, se recomienda que esta clase sea utilizada preferiblemente en lugar de StringBuffer pues será más rápida en la mayoría de los casos.

Las operaciones principales en StringBuilder son los métodos append e insert, cuando son sobrecargados para aceptar datos de cualquier tipo. Cada uno convierte con eficacia un dato dado a un string y añade o inserta los caracteres de ese string al string en construcción. El método append agrega siempre estos caracteres al final de la secuencia de caracteres en construcción; el método insert agrega los caracteres en un punto especificado.

Por ejemplo, si x refiere a un objeto StringBuilder que contiene “lava”, después de la llamada x.append(“manos”) del método haría que la secuencia construida contenga “lavamanos”, mientras que x.insert(4,“nos”) alteraría la construcción de la secuencia para contener “lavanosmanos”.

Generalmente si sb refiere a una instancia de StringBuilder, entonces sb.append(x) tiene el mismo efecto que sb.insert(sb.length(), x). Cada constructor de StringBuilder tiene una capacidad de almacenamiento. Mientras la longitud de la secuencia de caracteres contenida en el StringBuilder no exceda la capacidad, no es necesario asignar un nuevo buffer interno. Si desborda el buffer interno, automáticamente se hace más grande.

Las instancias StringBuilder no son seguras para el uso con múltiples hilos. Si se necesita o requiere la sincronización entonces se recomienda que StringBuffer sea utilizado.

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 50

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

5.4 Diferencias entre String, StringBuilder y StringBuffer

String es inmutable mientras que StringBuffer y StringBuilder pueden cambiar sus valores.

La única diferencia entre StringBuffer y StringBuilder es que StringBuilder es asíncrono mientras que StringBuffer es síncrono. Por lo tanto cuando una aplicación necesita funcionar solamente con un hilo entonces es mejor utilizar StringBuilder. StringBuilder es más eficiente que StringBuffer.

Criterios para elegir entre String, StringBuffer y StringBuilder:

• Si el texto no va a cambiar usar la clase String porque un objeto String es

inmutable. • Si el texto puede cambiar y es accedido solamente por un hilo, utilizar un

StringBuilder porque StringBuilder no es síncrono. • Si el texto puede cambiar, y es accedido por múltiples hilos, utilizar un

StringBuffer porque StringBuffer es síncrono.

6. Identificadores Cuando se escribe un programa se necesita almacenar los valores usados en el programa. Estos valores se almacenan en la memoria, se necesita tener un método simple para acceder a estas posiciones en la memoria. Por esto se usa un identificador o variable para referirnos a estas posiciones en memoria.

6.1 Convenciones de Nombres

Hay algunas reglas que tienen que seguirse al momento de nombrar variables en Java. Estas son:

• Los nombres de variables deben comenzar con una letra, subrayado (_) o dólar ($). Sin embargo, no hay restricción en el número de letras que se pueden usar.

• Los nombres de variables pueden contener letras, números, el subrayado (_) y el carácter dólar ($).

• No debe haber espacio entre los caracteres. • No hay límite en la longitud del nombre de la variable. • Las palabras clave de Java no pueden usarse como nombres de variables. • Para una mejor legibilidad, los nombres de variables deben componerse de dos

o más palabras significativas. La primera letra de la variable será siempre en minúsculas y las primeras letras de las palabras subsecuentes en mayúsculas (Ejemplo: numeroCuenta).

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 51

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

• En el caso de nombres de clase, todas las palabras que son parte del nombre de la clase deben comenzar con una letra mayúscula (Ejemplo: StringBuffer).

Se discute a continuación cómo se usa una variable.

7. Declaración e Inicialización de Variables Java es un lenguaje fuertemente tipificado, es decir, toda variable debe tener un tipo de dato asociado. Esto ayuda a saber el tipo del dato almacenado dentro de la variable o el tipo de dato que necesita ser almacenado dentro de la variable.

Ahora, para usar las variables, éstas tienen que ser declaradas. La declaración e inicialización consiste de los dos pasos siguientes:

• Especificar el tipo de dato de la variable, seguido por el identificador, como se muestra a continuación: int edad;

Aquí, int es el tipo de dato de la variable, y edad es el identificador.

• Inicializar la variable, donde el valor inicial es especificado. La inicialización de la variable se muestra a continuación:

edad = 18;

Se pueden combinar ambas, la declaración y la inicialización de la variable, en un mismo paso, como se muestra en la Figura 2.4.

Figura 2.4: Declaración e Inicialización de Variable

A continuación se discute el alcance de las variables.

7.1 Alcance de una Variable

Todas las sentencias de Java están especificadas dentro de un bloque (excepto para las sentencias package e import, que serán discutidas en el Volumen 2, Unidad 7 – Paquetes).

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 52

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

El inicio de un bloque se marca con un carácter ‘{‘, y el fin del bloque, con el correspondiente carácter ‘}’. Un bloque puede contener otro bloque (o cualquier número de bloques) dentro de él, estos se denominan bloques anidados.

Considere el caso de tres bloques anidados, como se muestra en la Figura 2.5.

Figura 2.5: Alcance de Variables

El bloque externo contiene al bloque del medio, que a su vez contiene al bloque interno. Suponga que una variable llamada edad se declara dentro del bloque del medio, entonces puede ser usada dentro del bloque del medio y del interno, pero no dentro del bloque externo. El rango de bloques dentro de la cual una variable se puede usar se conoce como alcance de una variable.

El Ejemplo 2.2 ilustra el alcance de una variable en un programa Java

Ejemplo 2.2

El código Java comienza aquí...

1. public class BloquePrueba {

2. /* Comienza el 1er bloque */

3. static int a = 10, b = 20;

4. public static void main(String args[]) {

5. /* Comienza el 2do bloque */

6. int c = 30;

7. System.out.println(a);

8. System.out.println(b);

9. System.out.println(c);

10. }/* Fin del 2do bloque */ 11. }/* Fin del 1er bloque */

El código Java termina aquí

Del código anterior, se puede ver que las variables a y b, declaradas en el primer bloque (el bloque externo), también son visibles en el segundo bloque (el bloque

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 53

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

interno). Sin embargo, lo contrario no es cierto, las variables declaradas dentro del segundo bloque no son visibles dentro del primer bloque. El alcance de una variable está limitado al bloque en la cual es declarada. La palabra clave static se usa para especificar que estas variables son variables de clase.

Fin del Ejemplo 2.2

Se discute a continuación acerca de varios operadores usados en Java.

8. Operadores en Java Cuando se escribe un programa, se usan numerosas expresiones para calcular algunos valores específicos. Estas expresiones hacen uso de varios operadores y son similares a expresiones aritméticas que usan muchos operadores. Las variables usadas en estas expresiones se llaman operandos. Existen algunos operadores que solo necesitan un operando, son llamados operadores unarios (ejemplo: ++). Los operadores que requieren dos operandos se llaman operadores binarios (por ejemplo, +), y los operadores que requieren tres operandos se llaman operadores ternarios (ejemplo:,? :).

Java soporta los siguientes tipos de operadores:

• Operadores Aritméticos. • Operadores Relacionales. • Operadores Condicionales. • Operadores Ternarios. • Operadores de Bits. • Operadores de Asignación.

8.1 Operadores Aritméticos

Los operadores aritméticos se usan para indicar operaciones aritméticas como adición, substracción, multiplicación, división y módulo. Los operadores aritméticos se muestran en la Figura 2.6.

Figura 2.6: Operadores Aritméticos

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 54

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

• +: El operador + se usa para indicar la operación de adición. Permite adicionar valores almacenados en dos o más variables. La siguiente expresión ilustra el uso del operador +: a + b

• -: El operador – se usa para indicar la operación de substracción. Permite substraer un valor almacenado en una variable de un valor almacenado en otra variable. La siguiente expresión ilustra el uso del operador –: a - b

• *: El operador * se usa para indicar la operación de multiplicación. Permite multiplicar valores almacenados en dos variables. La siguiente expresión ilustra el uso del operador *: a * b

• /: El operador / se usa para indicar la operación de división. Permite dividir un valor almacenado en una variable entre un valor almacenado en otra variable. La siguiente expresión ilustra el uso del operador /: a / b

• %: El operador % se usa para indicar la operación de módulo. Permite encontrar el residuo resultante de dividir un valor almacenado en una variable entre el valor almacenado en otra variable. La siguiente expresión ilustra el uso del operador %: a % b

Entre estos operadores aritméticos, el operador + está sobrecargado. Este operador se usa para concatenar dos cadenas de caracteres. El siguiente fragmento de código ilustra esto:

String str1 = "Pedro Perez apoyado sobre una pared. ";

String str2 = "Pedro Perez tuvo una gran caida";

String str3 = str1 + str2;

String str4 = "Pedro Perez apoyado sobre una pared. " +

"Pedro Perez tuvo una gran caida";

En el código anterior, ambos str3 y str4 tendrán ambos el string "Pedro Perez apoyado sobre una pared. Pedro Perez tuvo una gran caida".

Se puede concatenar un entero con un string, como se muestra en el siguiente código:

String str1 = "Numero de dias de la semana es: ";

int dias = 7;

String str2 = str1 + dias;

Aquí str2 tendrá el string "Numero de dias de la semana es: 7".

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 55

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

8.2 Operadores Relacionales

Los operadores relacionales se usan para comparar dos valores almacenados en variables. Los diferentes operadores relacionales se listan a continuación:

• <: El operador menor que < se usa para determinar si el valor almacenado en una variable es menor que el valor almacenado en otra variable. Cuando esta condición se satisface, el resultado de esta operación es ‘true’, caso contrario el resultado es ‘false’. La siguiente expresión ilustra el uso de este operador: a < b

• >: El operador mayor que > se usa para determinar si el valor almacenado en una variable es mayor que el valor almacenado en otra variable. Cuando esta condición se satisface, el resultado de esta operación es ‘true’, caso contrario el resultado es ‘false’. La siguiente expresión ilustra el uso de este operador: a > b

• <=: El operador menor o igual que <= se usa para determinar si el valor almacenado en una variable es menor o igual que el valor almacenado en otra variable. Cuando esta condición se satisface, el resultado de esta operación es ‘true’, caso contrario el resultado es ‘false’. La siguiente expresión ilustra el uso de este operador: a <= b

• >=: El operador mayor o igual que >= se usa para determinar si el valor almacenado en una variable es mayor o igual que el valor almacenado en otra variable. Cuando esta condición se satisface, el resultado de esta operación es ‘true’, caso contrario el resultado es ‘false’. La siguiente expresión ilustra el uso de este operador: a >= b

• ==: El operador de igualdad == se usa para determinar si el valor almacenado en una variable es igual al valor almacenado en otra variable. Cuando esta condición se satisface, el resultado de esta operación es ‘true’, caso contrario el resultado es ‘false’. La siguiente expresión ilustra el uso de este operador: a == b

• !=: El operador de no igual != se usa para determinar si el valor almacenado en una variable es diferente al valor almacenado en otra variable. Cuando esta condición se satisface, el resultado de esta operación es ‘true’, caso contrario el resultado es ‘false’. La siguiente expresión ilustra el uso de este operador: a != b

Tómese como ejemplo, dos números, 35 y 65, y determine que sucede cuando se usan los diferentes operadores relacionales en ellos.

• 35 < 65 resulta en true • 35 > 65 resulta en false • 35 <= 65 resulta en true

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 56

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

• 35 >= 65 resulta en false • 35 == 65 resulta en false • 35 != 65 resulta en true

A veces durante la ejecución, puede ser necesario encontrar la clase a la que un objeto pertenece. El operador instanceof devuelve true o false basado en si el operando izquierdo es una instancia del operando derecho.

Considere este ejemplo, asumiendo que mc es un objeto definido y MiClase es una clase Java, el operador instanceof se usa como sigue para saber si mc es una instancia de la clase MiClase.

mc instanceof MiClase

La sentencia anterior retorna true si es una instancia, false en caso contrario.

8.3 Operadores Condicionales

Generalmente los operadores condicionales se usan en combinación con los operadores relacionales para determinar si una condición es true o false. Los tres operadores condicionales se listan a continuación:

• &&: El operador && (AND) se usa para determinar si las condiciones a ambos lados del operador resultan en true o false. Primero se evalúa el resultado de la condición a la izquierda del operando, si resulta en true, entonces el resultado de la condición a la derecha del operador es evaluado. Si ambas condiciones resultan en true, entonces esta operación también resulta en true. Si la condición a la izquierda del operador resulta en false, la condición a la derecha del operador no es evaluada, y la operación completa resulta en false. La siguiente expresión ilustra el uso de este operador: (a < b) && (b < c)

• ||: El operador || (OR) se usa para determinar si al menos uno de las dos condiciones en alguno de los lados de este operador es true. Si la condición a la izquierda de este operador resulta en false, entonces la condición a la derecha es evaluada, si esta última condición resulta en true, entonces el resultado de la operación es true. Si la condición a la izquierda de este operador es true, entonces la condición a la derecha no es evaluada, y el resultado de la operación es true. La siguiente expresión ilustra el uso de este operador: (a < b) || (b < c)

• !: El operador ! (NOT) se usar para negar el resultado obtenido en una operación. Si el resultado de una operación es true, entonces el resultado de esta operación después de aplicar el operador ! es false, y al contrario, el caso que la operación es false, la operación completa es true. La siguiente expresión ilustra el uso del operador NOT: !(a < b)

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 57

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Estos operadores requieren dos operandos, por esto se denominan operadores binarios.

8.4 Operador Ternario

Como se mencionó anteriormente, en un operador ternario aparecen tres operandos. Java tiene un solo operador ternario llamado operador ? : . La sintaxis general de este operador es la siguiente:

variable = expresion ? operando1 : operando2

Aquí, expresion es evaluada. Si expresion retorna true, entonces operando1 se le asigna a variable. Si expresion retorna false, entonces operando2 se le asigna a variable.

Se presenta un ejemplo de código para entender mejor este operador. Se tienen dos variables var1 y var2, se quiere calcular cuál de las dos es más grande, y asignarla a mayor.

mayor = (var1 > var2) ? var1 : var2

Se entenderá el uso del operador ternario al tomar diferentes valores para var1 y var2.

var1 = 5 y var2 = 3.

La expresión var1 > var2 evalúa a true ya que 5 es mayor que 3.

Por lo tanto, el valor de var1, i.e. 5, se le asigna a mayor.

var1 = 6 y var2 = 12.

La expresión var1 > var2 evalúa a false ya que 12 es mayor que 6.

Por lo tanto, el valor de var2, es decir, 12, se le asigna a mayor.

8.5 Operadores de Bits

Los operadores de bits se usan para realizar operaciones de bits (operaciones sobre diferentes conjuntos de bits). Los operadores de bits son los siguientes:

• &: El operador & (AND) se usa para comparar los patrones de bits de los operandos a la izquierda y a la derecha bit-por-bit. La operación resulta en un conjunto de bits donde las posiciones de los bits que tienen 1 indica que las posiciones correspondientes en los operandos izquierdo y derecho también tienen el valor de 1.

La tabla de la verdad de un operador da el resultado de aplicar ese operador a las diferentes combinaciones de entradas. La Tabla 2.2 muestra la tabla de la verdad para el operador de bits &.

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 58

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Patrón de Bits 1 Patrón de Bits 2 Resultado

0 0 0

0 1 0

1 0 0

1 1 1

Tabla 2.2: Tabla de la Verdad del Operador de Bits AND (&)

Sea a = 3 cuyo patrón de bits es 00000011, sea b = 10 cuyo patrón de bits es 00001010. Cuando se efectúa la operación de bits &, c = a & b, el resultado almacenado en c es 2 cuyo patrón de bits es 00000010. El resultado se obtiene al realizar la operación & en cada bit de a con el correspondiente bit de b, como se muestra en la Figura 2.7.

Figura 2.7: Operador de bits &

• |: El operador | (OR) se usa para comparar bit-por-bit los conjuntos de bits a ambos lados del operador, y resulta en un conjunto de bits que indica si uno de los patrones de bits tiene 1 en esa posición.

La Tabla 2.3 muestra la tabla de verdad para el operador de bits OR

Patrón de Bits 1 Patrón de Bits 2 Resultado

0 0 0

0 1 1

1 0 1

1 1 1

Tabla 2.3: Tabla de la Verdad del Operador de Bits OR (|)

Sea a = 3 su patrón de bits es 00000011, sea b = 10 su patrón de bits es 00001010. Cuando se efectúa la operación de bits |, c = a | b, el resultado almacenado en c es 11 cuyo patrón de bits es 00001011. El resultado se obtiene al realizar la operación

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 59

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

OR en cada bit de a con el correspondiente bit de b, como se muestra en la Figura 2.8.

Figura 2.8: Operador de bits |

• ^: El operador ^ (XOR) se usa para evaluar los conjuntos de bits a ambos lados del operador, y resulta en un conjunto de bits que indica en que posiciones solo uno de los patrones de bits tiene un 1.

La Tabla 2.4 muestra la tabla de la verdad para el operador de bits ^.

Patrón de Bits 1 Patrón de Bits 2 Resultado

0 0 0

0 1 1

1 0 1

1 1 0

Tabla 2.4: Tabla de la Verdad del Operador de Bits XOR (^)

Sea a = 3 su patrón de bits es 00000011, sea b = 10 su patrón de bits es 00001010. Cuando se efectúa la operación de bits ^, c = a ^ b, el resultado almacenado en c es 9 cuyo patrón de bits es 00001001. El resultado se obtiene al realizar la operación ^ en cada bit de a con el correspondiente bit de b, como se muestra en la Figura 2.9:

Figura 2.9: Operador de bits ^

Operadores de desplazamiento de bits:

Los tres tipos de operadores de desplazamiento se basan en el mismo concepto que consiste en desplazar los bits del operando de la izquierda (A) tantas veces como lo indica el operando de la derecha (B).

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 60

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Tabla 2.5: Tabla de Operadores de Desplazamiento de bits

Para realizar cualquier tipo de desplazamiento, hay que recordar que el tipo de dato int es de 32 bits, y el tipo long, 64 bits y tanto short como byte son promovidos a int para ser representados en 32 bits para estas operaciones.

Si él operando (A) es un número negativo entonces la representación de A se hace a través de complemento a dos.

• <<: El operador de desplazamiento hacia la izquierda << desplaza a la izquierda un conjunto de bits una determinada cantidad de veces, en cada desplazamiento el bit de mayor orden se pierde y se coloca un cero a la derecha del número.

• >>: El operador de desplazamiento hacia la derecha >> desplaza a la derecha un conjunto de bits una determinada cantidad de veces, en cada desplazamiento se rellena el bit más significativo con su contenido previo y el bit menos significativo se pierde.

• >>>: El operador de desplazamiento hacia la derecha >>> desplaza a la derecha un conjunto de bits una determinada cantidad de veces, en cada desplazamiento el bit de menor orden se pierde y se coloca un 0 a la derecha del número, este desplazamiento se denomina “Desplazamiento sin Signo”.

Si al desplazar bits de un valor numérico, la cantidad (n) de bits a mover supera o iguala el máximo de bits representable por el tipo de dato (32 bits para int y 64 bits para long), los bits a desplazar serán n módulo (%) de 32 o de 64.

Vea los ejemplos mostrados en la Figura 2.10, que muestra el uso de los operadores de desplazamiento de bits.

Operador << >> >>>

Sintaxis A<<B A>>B A>>>B

Operación Desplaza los bits de A hacia la izquierda B veces

Desplaza los bits de A hacia la derecha B veces

Desplaza los bits de A hacia la derecha B veces, sin signo

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 61

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 2.10: Operadores de desplazamiento de bits

8.6 Operadores de Asignación

Los operadores de asignación se usan para asignar valores a las variables. El lado izquierdo de la asignación es la variable a la cual se le quiere asignar un valor. En el lado derecho se puede tener un valor o una expresión que resultará en el valor requerido. Los diferentes operadores de asignación se muestran en la Tabla 2.6:

Operador Uso Equivalente = var1 = var2 var1 = var2 += var1 += var2 var1 = var1 + var2 -= var1 -= var2 var1 = var1 - var2 *= var1 *= var2 var1 = var1 * var2 /= var1 /= var2 var1 = var1 / var2 %= var1 %= var2 var1 = var1 % var2 &= var1 &= var2 var1 = var1 & var2 |= var1 |= var2 var1 = var1 | var2 ^= var1 ^= var2 var1 = var1 ^ var2 <<= var1 <<= var2 var1 = var1 << var2 >>= var1 >>= var2 var1 = var1 >> var2 >>>= var1 >>>= var2 var1 = var1 >>> var2

Tabla 2.6: Tabla de Operadores de asignación

A continuación se discute el orden de precedencia entre estos operadores.

8.7 Precedencia Entre Operadores

Una expresión puede estar compuesta de muchos operadores y operandos. A mayor número de operadores y operandos en una expresión mayor su complejidad. Por lo tanto se necesita evaluar la expresión para encontrar su valor. Existe una convención

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 62

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

que se sigue que especifica la precedencia de cada operador sobre los otros. Esto se llama precedencia de operadores.

La lista siguiente muestra la precedencia de operadores. El operador con más alta precedencia encabeza la lista. Conforme se baja en la lista, la precedencia decrece. Los operadores con igual precedencia se muestran en la misma línea. Cuando se tienen operadores con igual precedencia en una expresión, el primer operador, de izquierda a derecha en la expresión, tiene mayor precedencia.

La Figura 2.11 ilustra la precedencia de los diferentes operadores en Java.

Figura 2.11: Precedencia de Operadores en Java

Las conversiones de un tipo de datos en otro es un punto importante en la programación en Java. Se aprenderá a continuación cómo se permiten las conversiones en Java.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 63

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

9. Conversión de Tipos Puede haber situaciones donde el resultado de una expresión será de un tipo en particular, pero tiene que ser asignado a una variable de un tipo diferente. Por ejemplo, se puede querer asignar el valor de una variable de punto flotante a una variable entera. Algunas veces, se quiere realizar una operación entre dos valores de diferentes tipos, Se puede querer convertir un valor de un tipo en otro tipo. Esto se llama conversión de tipos, y se puede hacer de dos formas:

• Conversión Automática. • Conversión Explícita.

9.1 Conversión Automática

Cuando se intenta asignar un valor de un tipo de dato más pequeño a un tipo de dato más grande, el compilador Java automáticamente convierte el valor del tipo de dato más pequeño al valor correspondiente en el tipo de dato más grande, y le asigna el valor a la variable del tipo de dato más grande. Considere una variable b, del tipo byte, que tiene el valor de 1. Cuando se intenta asignar esta variable b a una variable a del tipo int, no hay que preocuparse por errores de incompatibilidad de tipos. El compilador Java automáticamente convierte el valor byte de b a un valor int y se lo asigna a a. Esta conversión de tipos también es conocida como coerción automática.

El ejemplo será como sigue:

int a;

byte b = 1;

a = b; //Valor de b convertido a int automáticamente

9.2 Conversión Explícita

Para asignar un valor de un tipo de dato de un tamaño más grande a un tipo de dato más pequeño, el programador tiene que explícitamente especificar que el valor debe ser convertido al valor correspondiente en el tipo de dato más pequeño, y asignarlo a la variable del tipo de dato más pequeño. Esto se llama casting de tipos.

Observe la Figura 2.12, que muestra los tipos de datos donde la coerción automática de tipos toma lugar, además de cuando se requiere la conversión explícita.

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 64

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 2.12: Conversión Automática y Casting Explícito

Considere una variable b, del tipo int, que tiene el valor de 1. Cuando se intenta asignar esta variable b a una variable a del tipo byte, no hay que preocuparse por errores de incompatibilidad de tipos, al realizar la conversión explícita, el compilador Java convierte el valor int de b a un valor byte, y se lo asigna a a. La expresión será la siguiente:

byte a;

int b = 1;

a = (byte) b;//Valor de b convertido a int explícitamente

La Figura 2.13 muestra varios ejemplos de combinaciones de tipos de datos, en algunos se aplica la coerción automática, en otros se requiere la conversión de tipos explícita.

Figura 2.13: Conversión Automática y Conversión Explícita

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 65

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Java 5.0 ha incorporado un nuevo tipo de conversión automática entre las clases envolventes y los tipos de datos primitivos. Este tipo de conversión se realizaba manualmente por métodos proporcionados en las clases envolventes (clases Wrappers). Bajo este esquema se introducen los siguientes terminos:

Auto-boxing: Se refiere a las conversión automática de un tipo de dato primitivo a su correspondiente clase envolvente.

Auto-unboxing: Se refiere a las conversión automática de una clase envolvente a su correspondiente tipo de dato primitivo.El proceso manual se tornaba mecánico y tedioso, por ello fueron integrados los mecanismos de auto-boxing y auto-unboxing para permitir la conversión de valores primitivos hacia sus respectivos objetos envolventes de manera directa y sin mayores complicaciones.

El Ejemplo 2.3 ilustra el uso auto-boxing y auto-unboxing en Java 5.0.

Ejemplo 2.3

El código Java comienza aquí...

1. /*Definicion de la clase comienza aqui*/

2. public class ConversionEnvolventePrimitivoEjemplo {

3. /*El metodo main comienza aqui */

4. public static void main(String[] args) {

5. // Contador de vueltas como objeto con

6. // asignacion de un primitivo

7. Integer vuelta = 0;

8. // Parametros

9. double kilometros = 2.5;

10. int tiempo = 2; 11. 12. while (true) { 13. // Utilizando auto-incremento sobre objeto Integer 14. System.out.print("Vuelta: " + vuelta++); 15. // Operacion entre objeto Integer y primitivo double 16. System.out.print(" Distancia: " + vuelta * kilometros); 17. // Operacion entre objeto Integer y primitivo int 18. System.out.println(" Tiempo: " + vuelta * tiempo); 19. // Comparacion sobre objeto Integer 20. if (vuelta > 5) 21. break; 22. } // Fin del ciclo While

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 66

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

23. }/* El metodo main termina aqui */ 24. }/*Definicion de la clase termina aqui*/ El código Java termina aquí Salida:

Vuelta: 0 Distancia: 2.5 Tiempo: 2

Vuelta: 1 Distancia: 5.0 Tiempo: 4

Vuelta: 2 Distancia: 7.5 Tiempo: 6

Vuelta: 3 Distancia: 10.0 Tiempo: 8

Vuelta: 4 Distancia: 12.5 Tiempo: 10

Vuelta: 5 Distancia: 15.0 Tiempo: 12

Del código anterior se puede observar que no fue necesario hacer ningún tipo de conversión explicita entre un primitivo y un objeto envolvente en varias ocasiones.

Lo primero fue la asignación de un entero de tipo int al objeto Integer, sin la necesidad de usar el operador new. Luego, dentro del bloque while se realizan operaciones matemáticas e incremento en reiteradas ocasiones, para finalizar con la comparación sobre el objeto Integer con un primitivo de tipo int.

Fin del Ejemplo 2.3 Se han estudiado los tipos de datos primitivos en Java. A continuación se aprenderá acerca de los arreglos que son uno de los tipos referencias en Java.

10. Arreglos Los arreglos se usan para almacenar varios valores de un mismo tipo de datos. Asuma que se necesita almacenar los nombres de 100 empleados de una compañía. Si no se usan arreglos, se tendrían que usar 100 variables diferentes para almacenar los nombres de los empleados. Los arreglos son útiles en estas situaciones, debido a que no se tiene que declarar, inicializar y recordar 100 nombres de variables.

El índice en un arreglo se usa para identificar cada elemento del arreglo. En el ejemplo anterior, el índice del primer elemento será 0, el índice del segundo, será 1, y así sucesivamente. El índice del 100th elemento será 99. Por lo tanto, se puede acceder al nombre de un empleado específico fácilmente usando el índice correspondiente al empleado. Vea la Figura 2.14, que representa los índices en arreglos en Java.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 67

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 2.14: Índices de Arreglos en Java

En los arreglos también se pueden realizar funciones como ordenamiento, búsqueda, mezcla, etc.

Los arreglos sólo pueden almacenar un tipo de valor, donde tipo es cualquier tipo de datos presente en Java. Considere el caso de un arreglo de enteros, cada entero toma 4 bytes en la memoria. Por lo que, elementos adyacentes en el arreglo, están separados por 4 bytes. Similarmente, si se tiene un arreglo de caracteres, los elementos adyacentes están separados por 2 bytes, ya que el carácter ocupa 2 bytes cuando se almacena en la memoria.

La Tabla 2.7 muestra un arreglo de enteros usada para almacenar el pago básico de cinco empleados.

4000 5000 12000 6000 7500

Tabla 2.7: Arreglo de Pago Básico a Empleados (Una Dimensión)

La Tabla 2.8 muestra un arreglo de enteros usado para almacenar la Renta Permitida para cada empleado. La Renta Permitida se calcula como el 20% del pago básico del empleado.

800 1000 2400 1200 1500

Tabla 2.8: Arreglo de Renta Permitida por Empleado (Una Dimensión)

10.1 Crear Arreglos en Java

En Java, se tiene más de una forma de crear un arreglo. Los arreglos son objetos propios de Java, a diferencia en C o C++. Por lo que ellos deben crearse usando la palabra clave new.

int x[] = new int[5];

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 68

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Los arreglos necesitan ser inicializados antes de ser usados.

Nota: Los arreglos en Java mantienen sus tamaños individuales, a diferencia de en C o C++. Los arreglos tienen un miembro llamado length, que retorna el tamaño del arreglo. El siguiente comando retornará la longitud del arreglo x, que ya ha sido creado.

int size = x.length;

Hay también otras formas de crear arreglos en Java.

Considere lo siguiente:

int x[] = {5,2,0};

int []x = {5,2,0};

Las instrucciones anteriores inicializan un arreglo con tres valores enteros. El tamaño está implícito en este caso.

Se puede también simultáneamente crear y asignar valores en los arreglos. Esto se hace de la siguiente manera:

String [] s = new String[] {"uno", "dos"};

Considere la Figura 2.15, que resume las diferentes formas de crear arreglos en Java.

int x[] = {5, 2, 0};

float arregloFloat[] = new float[10];

String[] s1 = {"uno", "dos"};

String[] s2 = new String[]{"uno", "dos"};

Figura 2.15: Crear de Arreglos en Java

El programa a continuación declara dos arreglos unidimensionales. Un arreglo se usa para almacenar el pago básico de cinco empleados (inicializados con su salario base). La Renta Permitida de cada empleado se almacena en el segundo arreglo en el índice correspondiente donde se almacena el salario base. El Ejemplo 2.4 ilustra como acceder a cada elemento del arreglo.

Ejemplo 2.4

El código Java comienza aquí…

1. /*Definicion de la clase comienza aqui*/

2. public class ArregloUnidimensionalEjemplo {

3. /*El metodo main comienza aqui */

4. public static void main(String args[]) {

5. // Arreglo sueldo basico emppleado

6. double empSueldo[] = {4000, 5000, 12000,

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 69

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

7. 6000, 7500};

8. // Arreglo renta permitida por emppleado

9. double empRenta[] = new double[5];

10. int i; 11. 12. for (i = 0; i < 5; i++) { 13. empRenta[i] = .2 * empSueldo[i]; 14. }// Fin del ciclo for 15. 16. System.out.println("Detalle Sueldo basico y Renta"); 17. for (i = 0; i < 5; i++) { 18. System.out.println(empSueldo[i] + "\t" + empRenta[i]); 19. }// Fin del ciclo for 20. }/* El metodo main termina aqui */ 21. }/* Definicion de la clase termina aqui */

El código Java termina aquí

La salida del código anterior es la siguiente: Detalle Sueldo basico y Renta

4000.0 800.0

5000.0 1000.0

12000.0 2400.0

6000.0 1200.0

7500.0 1500.0

Fin del Ejemplo 2.4

En el programa anterior se usan dos arreglos separados para almacenar el salario base y la Renta Permitida de los empleados. Estos son arreglos unidimensionales. En lugar de usar dos arreglos unidimensionales, puede usar un arreglo bidimensional. Este arreglo bidimensional puede ser visualizado como una tabla con cinco filas (una por cada empleado) y dos columnas (una para el salario base y otra para la Renta Permitida), como se muestra en la Tabla 2.9.

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 70

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

4000 800

5000 1000

12000 2400

6000 1200

7500 1500

Tabla 2.9: Arreglo de Salario Base y Renta Permitida por Empleado (Bidimensional)

El Ejemplo 2.5 muestra como trabajar con arreglos de dos dimensiones en Java.

Ejemplo 2.5

El código Java comienza aquí...

1. /*Definicion de la clase comienza aqui*/ 2. public class ArregloBidimensionalEjemplo { 3. /* Metodo main comienza aqui */ 4. public static void main(String args[]) { 5. // Arreglo sueldo basico y renta 6. // permitida por emppleado 7. double empArreglo[][] = { 8. { 4000, 0}, 9. { 5000, 0}, 10. {12000, 0},

11. { 6000, 0},

12. { 7500, 0}

13. };

14. int i, j;

15. double basico = 0.0;

16.

17. for (i = 0; i < 5; i++) {

18. for (j = 0; j < 2; j++) {

19. if (j == 0)

20. basico = empArreglo[i][j];

21. else

22. empArreglo[i][j] = 0.2 * basico;

23. }// Fin lazo for

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 71

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

24. }// Fin lazo for

25.

26. System.out.println("Detalle Sueldo basico y Renta");

27. for (i = 0; i < 5; i++) {

28. for (j = 0; j < 2; j++)

29. System.out.print(empArreglo[i][j] + "\t");

30. System.out.println();

31. }// Fin lazo for

32. }/* Metodo main termina aqui */

33. }/* Definicion de la clase termina aqui */

El código Java termina aquí

La salida del código anterior es como sigue: Detalle Sueldo basico y Renta

4000.0 800.0

5000.0 1000.0

12000.0 2400.0

6000.0 1200.0

7500.0 1500.0

Fin del Ejemplo 2.5

El programa anterior ilustra la creación y el uso de un arreglo bidimensional en Java. Seguidamente se estudiará la forma en la cual se pueden añadir más dimensiones a un arreglo en Java.

Java provee estructuras de control como otros lenguajes de programación. A continuación se aprenderá acerca de ellos.

11. Estructuras de Control Las estructuras de control en Java le permiten al programador controlar el flujo de ejecución del programa. Las diferentes estructuras de control (llamadas también construcciones) disponibles en Java son: if-else, for, while, do while y switch-case. Asociadas con estas construcciones están las sentencias, break y continue.

11.1 La Construcción if–else

La construcción if-else se usa cuando se necesita decidir cual de los caminos disponibles va a ser tomado basados en cierta condición. Si la condición evaluada es verdadera, la sentencia que sigue a la construcción if es ejecutada.

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 72

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

La sintaxis de la construcción if es como sigue:

if (booleanExp)

sentencia;

La sintaxis de la construcción if…else es como sigue:

if (booleanExp)

sentencia1;

else

sentencia2;

Java requiere que el resultado de booleanExp sea de tipo Booleano, en caso contrario el compilador de Java genera un error. Si la condición que es evaluada es falsa, entonces las sentencias que siguen a la construcción else son ejecutadas. La estructura general de la sentencia if-else se muestra a continuación:

if(booleanExp){

sentencia1;

sentencia2;

.

.

.

sentenciaN;

}

else{

sentencia1;

sentencia2;

.

.

.

sentenciaN;

}

Nota: El punto y coma se usa como delimitador para todas las sentencias en Java. Una sentencia que termina con un punto y coma se llama una sentencia simple; por el otro lado, conjuntos de sentencias que están encerradas dentro de llaves se denominan sentencias compuestas. Las sentencias compuestas son un conjunto de sentencias simples que tienen una funcionalidad común, y por esto se les considera como un bloque.

Se puede tener una construcción if-else dentro de otra. Esto se conoce como sentencias if-else anidadas. No existe restricción en el nivel de complejidad de esta

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 73

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

construcción. La estructura general de una sentencia if-else anidada se muestra a continuación:

if(booleanExp1){

.

.

.

if(condicion2){

sentencia1;

else

sentencia1;

.

.

.

}

else{

if(booleanExp2){

sentencia1;

sentencia2;

.

sentenciaN;

}

else

sentencia1;

sentenciaN; }

Considere el segmento de código mostrado en la Figura 2.16, que ejemplifica el uso de la construcción if-else.

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 74

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 2.16: Uso de la Construcción if-else

11.2 El Ciclo for

El ciclo for se usa para realizar un conjunto de operaciones repetidamente hasta que alguna condición se satisfaga o para realizar un conjunto de operaciones infinitamente.

La sintaxis general del ciclo for se muestra a continuación:

for (inicializacion; booleanExp; incrementoExp)

sentencia;

La sintaxis anterior muestra sólo una sentencia dentro del ciclo for. El ciclo for puede también tener sentencias compuestas, encerradas dentro de { }. La estructura general de un ciclo for con más de una sentencia se muestra a continuación:

for(inicializacion; booleanExp; incrementoExp){

sentencia1;

sentencia2;

.

.

.

sentenciaN;

}

Se puede ver que el ciclo for tiene cuatro partes, siendo éstas: inicialización, expresión booleana, expresión de incremento y cuerpo. El ciclo for usa un contador para llevar el número de veces que el ciclo ha sido ejecutado. Este contador es inicializado a un valor apropiado en la parte de inicialización, y es actualizado en la parte de actualización, donde el incremento toma lugar. El contador es revisado contra la condición requerida antes que las sentencias en el cuerpo del ciclo sean ejecutadas. Si la condición resulta

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 75

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

en true, las sentencias en el cuerpo del ciclo for son ejecutadas, y si resulta en false, la sentencia siguiente al final del ciclo for se ejecuta.

Se pueden tener ciclos for anidados, en los cuales se tiene un ciclo for dentro de otro. No hay restricción en el número de ciclos for que se pueden tener dentro de un ciclo for. La estructura general de un ciclo for anidado se da a continuación:

for(inicializacion; booleanExp; incrementoExp){

sentencia1;

sentencia2;

for(inicializacion; booleanExp; incrementoExp){

sentencia1;

sentencia2;

.

.

.

sentenciaN;

}

.

.

.

sentenciaN;

}

Considere la Figura 2.17, que muestra el uso del ciclo for en Java. El ciclo for que se muestra a continuación calcula la suma de todos los elementos de un arreglo.

int a[] = {1, 2, 3, 4, 5};

int suma = 0;

for (int i = 0; i<a.length; i++){

suma = suma = a[i];

}

System.out.println("suma = " + suma);

Figura 2.17: Uso del Ciclo for

Se puede tener un ciclo infinito también, como sigue:

for( ; ; ){

sentencia1;

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 76

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

sentencia2;

.

.

sentenciaN;

}

En la discusión de la construcción for, se ha estado usando incrementoExp, para hacer referencia a la expresión de incremento del contador del ciclo, pero esta expresión también puede ser usada para decrementar este contador.

Java 5.0 ha incorporado una nueva sintaxis para el ciclo for, con el cual se pretende simplificar su uso.

La nueva sintaxis del ciclo for se muestra a continuación:

for ([Tipo] identificador : arreglo|coleccion){

sentencia1;

sentencia2;

.

.

sentenciaN;

}

Observe el siguiente ejemplo, que muestra el uso del ciclo for en Java 5.0 con la nueva sintaxis. El ciclo for que se muestra a continuación hace lo mismo que el ejemplo de la Figura 2.17.

int a[] = {1, 2, 3, 4, 5};

int suma = 0;

for (int numero : a) {

suma = suma + numero;

//suma += numero;

}

System.out.println("suma = " + suma);

El uso de las Colecciones serán tratadas en detalle en el Volumen 8 – Conceptos Avanzados, Unidad 1 – API de Colecciones.

También se puede alcanzar la misma funcionalidad de ciclos usando los ciclos while en Java.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 77

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

11.3 El Ciclo while

El ciclo while se usa para realizar un conjunto de operaciones repetidamente hasta que alguna condición es satisfecha, o para realizar un conjunto de operaciones infinitamente.

La sintaxis general del ciclo while es la siguiente:

while (booleanExp)

sentencia;

Como en el ciclo for, el ciclo while puede también tener más de una sentencia en el cuerpo del ciclo. La estructura general del ciclo while, donde el cuerpo del ciclo tiene más de una sentencia, es la siguiente:

while(booleanExp){

sentencia1;

sentencia2;

.

.

.

sentenciaN;

}

Si la condición booleanExp resulta en true, las sentencias en el cuerpo del ciclo son ejecutadas, y si resulta en false, la sentencia que sigue al final del ciclo while es ejecutada.

Un segmento de código escrito usando el ciclo for puede ser convertido en un ciclo while y viceversa.

La Figura 2.18 muestra el uso del ciclo while para encontrar la suma de todos los elementos de un arreglo.

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 78

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

int a[] = {1, 2, 3, 4, 5};

int suma = 0;

int i = 0;

while (i < a.length){

suma = suma + a[i];

i = i + 1;

// suma += a[i++];

}

System.out.println("suma = " + suma);

Figura 2.18: Uso del Ciclo while

Se pueden tener ciclos while anidados, en los que se tiene un ciclo while dentro de otro. No hay restricción en el número de ciclos while que se pueden tener dentro de un ciclo while. La estructura general de esta forma del ciclo while se da a continuación:

while(booleanExp){

sentencia1;

sentencia2;

while(booleanExp2){

sentencia1;

sentencia2;

.

.

.

sentenciaN;

}

.

.

.

sentenciaN;

}

También se puede tener un ciclo while infinito, como sigue:

while( true ){

sentencia1;

sentencia2;

.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 79

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

.

sentenciaN;

}

11.4 El Ciclo do-while

El ciclo do-while se usa para realizar un conjunto de operaciones repetidamente hasta que alguna condición sea satisfecha, o para realizar un conjunto de operaciones infinitamente. La siguiente instrucción muestra la sintaxis general del ciclo do-while.

do {

sentencia;

} while (booleanExp);

La estructura general de un ciclo do-while que tiene más de una instrucción en su cuerpo se da a continuación:

do{

sentencia1;

sentencia2;

.

sentenciaN;

}while(booleanExp);

Note que las sentencias se ejecutan antes de preguntar por la condición. Si la condición resulta en true, las sentencias en el cuerpo del ciclo do-while son ejecutadas nuevamente, y si el resultado es false, la sentencia que esta después del final del ciclo do-while es ejecutada. Esto garantiza que las sentencias en el cuerpo del ciclo do-while son ejecutadas al menos una vez, a diferencia del ciclo while y el ciclo for, en donde si la condición no es cumplida la primera vez nunca se ejecutan las sentencias ubicadas dentro de estos ciclos.

Se puede comparar el ciclo do-while con el ciclo for, o un ciclo while. El código escrito usando el ciclo do-while puede ser convertido en un ciclo while o a un ciclo for y viceversa.

Considere la Figura 2.19, muestra el uso del ciclo do-while para calcular la suma de todos los elementos de un arreglo.

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 80

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

int a[] = {1, 2, 3, 4, 5};

int suma = 0;

int i = 0;

do{

suma = suma + a[i];

i = i + 1;

// suma += a[i++];

}while (i < a.length);

System.out.println("suma = " + suma);

Figura 2.19: Uso del Ciclo do-while

Se pueden tener dos o mas ciclos do-while anidados, en el cual se tienen ciclos do-while dentro de otros. No hay restricción en el número de ciclos do-while que se pueden tener dentro de otro ciclo do-while. La estructura general de los ciclos do-while anidados se muestra a continuación:

do{

sentencia1;

sentencia2;

do{

sentencia1;

sentencia2;

.

.

.

sentenciaN

} while(booleanExp);

.

.

.

sentenciaN;

} while(booleanExp2);

Se puede tener un ciclo do-while infinito también, como sigue:

do {

sentencia1;

sentencia2;

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 81

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

.

.

sentenciaN;

} while( true );

11.5 La Construcción switch-case

La construcción switch-case se usa para realizar una (o algunas) de varias operaciones basadas en el resultado de una condición.

La estructura general de la construcción switch-case se da a continuación:

switch(valor){

case val1:

sentencia1

sentencia2

.

.

sentenciaN

break;

case val2:

sentencia1

sentencia2

.

.

sentenciaN

break;

.

.

case valN:

sentencia1

sentencia2

.

.

sentenciaN

break;

default:

sentencia1;

sentencia2;

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 82

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

.

sentenciaN;

}

Aquí, se usa la sentencia break después de que todas las instrucciones dentro de un case particular son ejecutadas. La sentencia break ocasiona que el flujo de control salga de la construcción switch-case. Si no se usa la sentencia break, todas las sentencias que están después del case que concuerde hasta el fin del bloque, serán ejecutadas.

A continuación se aprenderá acerca de las sentencias break y continue.

11.6 La Sentencia break

La sentencia break se usa para sacar el control del flujo de ejecución del bloque más interno donde es ejecutado de forma que la sentencia siguiente al bloque sea ejecutada. El siguiente código muestra el uso de la sentencia break en un ciclo for para sacar el flujo de control fuera del ciclo.

for(int i = 0; i<10; i++){

sentencia1;

.

if(booleanExp)

break;

sentenciaN;

}

11.7 La Sentencia continue

La sentencia continue se usa para regresar el flujo de ejecución al inicio del bloque más interno donde es ejecutada. El siguiente código muestra el uso de la sentencia continue en un ciclo for. Lleva el flujo de control al inicio del ciclo.

for(int i = 0; i<10; i++){

sentencia1

.

if(condicion)

continue;

sentenciaN

}

Considere la Figura 2.20, que muestra las sentencias break y continue.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 83

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 2.20: Uso de las Sentencias break y continue

11.8 Las Sentencias break y continue con Etiquetas

Las etiquetas permiten identificar las sentencias. Esto se hace ubicando antes de la sentencia un nombre seguido por dos puntos (:). La sentencia que se identifica se refiere a cualquier sentencia simple o bloque de sentencias. Su forma general es:

etiqueta:sentencia;

Ya se ha estudiado el uso de la sentencia break. Como se recordará la sentencia break cambia el control del flujo de ejecución para que se dirija fuera del ámbito donde se ubicaba dicha sentencia.

Existe otra modalidad de break que hace que el flujo de control salte fuera de un ciclo identificado con una etiqueta. La sintaxis general se muestra a continuación:

break etiquetaUno; //etiquetaUno identifica a un ciclo

De igual manera la sentencia continue se puede utilizar como una sentencia etiquetada. La diferencia es que esta instrucción hace que el flujo de control se dirija a una sentencia identificada mediante una etiqueta. La sintaxis de una sentencia continue con etiqueta es la siguiente:

continue etiquetaDos; //etiquetaDos identifica a un ciclo Una particularidad de la sentencia continue en comparación con la sentencia break es que siendo o no etiquetada sólo puede estar ubicada dentro de ciclos iterativos. El siguiente extracto de código muestra como se utilizan el break y el continue con etiquetas.

El código Java comienza aquí...

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 84

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

1. etiquetaUno:

2. for(int i=0;i<2;i++){

3. System.out.println("En Ciclo Uno");

4. etiquetaDos:

5. for(int j=0;j<2;j++ ){

6. System.out.println("En Ciclo Dos");

7. if(j==0)

8. continue;

9. if(j==1)

10. break etiquetaUno;

11. if(j==2)

12. continue etiquetaUno;

13. }

14. } El código Java termina aquí Salida:

En Ciclo Uno

En Ciclo Dos

En Ciclo Dos

Cuando j sea igual a 0, el control de flujo permanecerá en el ciclo más interno y continuará la ejecución para la iteración donde j es igual a 1.

Cuando j es igual a 1, el control de flujo sale fuera del ciclo principal y en consecuencia fuera del ciclo más interno, terminado así con la ejecución del código. La variable j nunca valdrá 2.

Si la línea (10) del fragmento de código anterior se sustituye por la línea: break etiquetaDos; La salida al ejecutar dicha aplicación será: En Ciclo Uno En Ciclo Dos En Ciclo Dos En Ciclo Uno En Ciclo Dos En Ciclo Dos

Cuando j es igual a 1, el control de flujo sale fuera del ciclo más interno únicamente, permitiendo que el ciclo más externo realice las dos iteraciones establecidas por su condición, es decir, para i =0 e i =1 respectivamente.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 85

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Nota: Sí la línea (8) del fragmento de código anterior se sustituye por la línea:

continue etiquetaUno;

La salida al ejecutar dicha aplicación será: En Ciclo Uno En Ciclo Dos En Ciclo Uno En Ciclo Dos

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 86

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Resumen Ahora que ha completado esta unidad, usted debe ser capaz de:

• Discutir los tipos de datos primitivos en Java. • Describir la declaración e inicialización de variables en Java. • Mencionar los diferentes operadores usados en Java. • Explicar la precedencia de operadores en Java. • Definir los tipos de conversiones automática y explícita en Java. • Explicar las diferentes estructuras de control usadas en Java.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 87

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 2: Examen de Autoevaluación 1) En Java, una variable boolean puede almacenar un valor de 0 o 1.

a) Verdadero b) Falso

2) ¿Cuáles de los siguientes pertenecen al tipo de datos entero?

a) array b) double c) char d) byte

3) ¿Cuál de las siguientes codificaciones se usa para codificar caracteres en Java?

a) Unicode b) ASCII c) Bytecode d) Codificación Internacional

4) ¿Qué tipo de operador es '|'?

a) Operador de Bits b) Operador Lógico c) Operador Condicional d) No existe este operador

5) ¿Cuál de los siguientes grupos de operadores tienen una prioridad más alta que

los operadores de igualdad? a) Unarios b) Relacionales c) De Bits d) De desplazamiento

6) ¿Para cuál de los siguientes tipos primitivos están disponibles clases envolventes?

a) int b) byte c) float d) char

Core Java Guía del Estudiante

Unidad 2: Operadores, Expresiones y Control de Flujo Libro 1: Core Java 88

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

7) ¿Qué pasa cuando se usa for(; ;) en un programa Java? a) Ocurre un error de compilación b) No se entra al ciclo c) El ciclo se ejecuta infinitas veces d) Ninguna de las anteriores

8) ¿Cuál de las siguientes sentencias se usa para salir de un ciclo?

a) break b) continue c) exit d) Todas las anteriores

9) ¿Cuál ciclo en Java evalúa la expresión boolean al final del ciclo?

a) while b) for c) switch d) do-while

10) Un ciclo do-while se ejecuta al menos una vez aún si la condición revisada es

false. a) Verdadero b) Falso

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 1: Fundamentos de Java 89

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Respuestas a la Unidad 2: Examen de Autoevaluación 1) b 2) c y d 3) a 4) a 5) a, b y d 6) a, b, c y d 7) c 8) a 9) d

10) a

Core Java Guía del Estudiante

Unidad 3: Lab. de Operaciones, Expresiones y Control de Flujo Libro 1: Core Java 90

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 3: Lab. de Operaciones, Expresiones y Control de Flujo

Objetivos del Aprendizaje Al final de esta unidad, usted será capaz de:

• Trabajar con operadores aritméticos. • Usar operadores de bits. • Trabajar con ciclos en Java. • Usar arreglos en Java.

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 3: Lab. de Operaciones, Expresiones y Control de Flujo 91

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Ejercicios de Laboratorio 1) Escriba un programa para crear una clase llamada Calculadora que usa

operadores aritméticos y también operadores de bits (&, | y ^). Inicialice las variables con cualquier valor aceptable de su elección y demuestre el uso de estos operadores.

Consejos Útiles:

• Cree una clase llamada Calculadora. • Declare dos variables enteras e inicialícelas con dos valores (por ejemplo 10 y

5). • Sume, reste, multiplique y divida estas dos variables e imprima los resultado en

la salida estándar. • Realice un AND (&), OR (|) y un XOR (^) bits en estas dos variables e imprima

los resultado en la salida estándar. 2) Escriba un programa en Java usando, un ciclo while o un do-while, para

imprimir el conjunto completo de los números Armstrong de tres dígitos. Un número Armstrong es aquel que satisface la siguiente condición:

a3 + b3 + c3 = abc. Este es un ejemplo de un número Armstrong : 13 + 53 + 33 = 153

Consejos Útiles: • Cree una clase llamada NumerosArmstrong. • Escriba un ciclo for con el valor de la variable contadora variando desde 100

hasta 999. • Extraiga cada dígito de la variable contadora. • Eleve al cubo cada uno de los dígitos y súmelos. • Verifique si la suma de los cubos es igual a la variable contadora. • Si son iguales, imprima el mensaje ‘Este es un número Armstrong’.

3) Se da como entrada para un programa Java una oración larga terminada con un

carácter nuevalinea. La oración puede contener letras, dígitos y caracteres especiales. Se requiere que se escriba un programa de Java que cuente el número de letras, dígitos, espacios en blanco, además de otros caracteres y los muestre de la siguiente forma:

Ejemplo :

Entrada : ¡Muéstrelos (:,*,; etc.) en una forma adecuada! Salida :

Letras : 31

Dígitos : 0

Core Java Guía del Estudiante

Unidad 3: Lab. de Operaciones, Expresiones y Control de Flujo Libro 1: Core Java 92

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Espacios en blanco : 6

Otros : 10

Consejos Útiles:

• Escriba una clase llamada Contador. • Declare una variable String, str e inicialícela con la oración por ejemplo.

“¡Muéstrelos (:,*,; etc.) en una forma adecuada!\n”. • Forme un arreglo de caracteres a partir de la variable str, usando el método

toCharArray() de String. • Cree un ciclo for (haciendo uso de su nueva sintaxis), que opere con el arreglo

de caracteres y asigne cada uno de los elementos en una variable Character llamada caracter.

• Use el método Character.isLetter() para revisar si un carácter en el arreglo es una letra y cuente el número de letras.

• Use el método Character.isDigit() para revisar si un carácter en el arreglo es un dígito y cuente el número de dígitos.

• Use el método Character.isWhitespace() para revisar si un carácter en el arreglo es un espacio en blanco y cuente el número de espacios en blanco.

• Si el carácter en el arreglo no es ni una letra, ni un dígito, ni un espacio en blanco, se clasifica como otros. Cuente el número de caracteres clasificados como otros.

• Imprima el número de letras, dígitos, espacios en blanco y otros caracteres en la salida estándar.

4) Escriba un programa que encuentre el mínimo número de billetes tipo moneda

requeridos para formar un monto específico (no se necesita tomar la entrada del usuario) asuma que los billetes moneda de denominaciones 500,100,50,20,10,5,2, y 1 dólar están disponibles.

Si el monto es 1239,

El programa debe imprimir:

Monedas de 500: 2

Monedas de 100: 2

Monedas de 50: 0

Monedas de 20: 1

Monedas de 10: 1

Monedas de 5: 1

Monedas de 2: 2

Monedas de 1: 0

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 3: Lab. de Operaciones, Expresiones y Control de Flujo 93

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Consejo: Puede usar algunos métodos relacionados a caracteres en la cuarta pregunta, la cual requiere de la clase Character que está disponible en el paquete java.lang.

Consejos Útiles:

• Escriba una clase llamada MinimoMonedas.

• Declare una variable entera llamada numero e inicialícela con un entero válido (por ejemplo 54321).

• 5) Calcule la denominación de 500, 100, 50, 20, 10, 5, 2 y 1 billetes de dólar que

formarán el 54321 e imprímalos en la salida estándar.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 95

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Volumen 2: Programación Orientada a Objetos

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 97

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 1: Clases y Objetos

Objetivos del Aprendizaje Al final de esta unidad, usted será capaz de:

• Explicar los conceptos de clases y objetos. • Discutir acerca de la estructura y miembros de una clase Java. • Definir variables y métodos en Java. • Explicar los modificadores de acceso. • Explicar la necesidad de y uso de constructores para una clase. • Explicar cómo los métodos en una clase Java pueden ser sobrecargados. • Definir y usar clases anidadas. • Discutir cómo Java maneja los argumentos de línea de comandos. • Explicar el ciclo de vida de un objeto. • Describir el manejo de memoria en Java. • Exponer el uso de Enumeraciones.

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 98

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

1. Introducción En el volumen anterior, se tuvo una visión general de la programación en Java. Se estudiaron los operadores, expresiones y sentencias de control de flujo. En esta unidad, se discuten clases y objetos en Java.

Todos los días, son empleados numerosos objetos en nuestras vidas, algunos de los cuales tienen ciertas características comunes que los hacen pertenecer a una categoría particular. Por ejemplo, John Davenport y Edna Smith son estudiantes en una universidad. Ambos tienen algunos atributos en común como el nombre, edad, número de identificación del estudiante, nombre de la universidad, carrera estudiando, estatus del estudiante, cursos registrados, calificaciones obtenidas, y así sucesivamente, que son comunes a cualquier estudiante. Aunque ellos comparten este conjunto de atributos, los valores de los atributos serán diferentes y específicos para cada persona.

Similarmente, el carro de John y el de Edna pertenecen a una categoría llamada carro. Algunos de los atributos comunes a esta categoría son: número de placa del carro, fecha de fabricación, tipo de carro, etc. En un escenario orientado a objetos, John y Edna son objetos de la clase estudiante y sus carros son objetos de la clase carro. A continuación se aprenderá más acerca de clases y objetos.

2. Clases y Objetos Una vez vistos algunos ejemplos del mundo real de clases y objetos, se les va a definir formalmente.

Una clase es una entidad auto contenida que provee una plantilla (framework) para definir atributos y comportamiento encontrados comúnmente en objetos de software pertenecientes a un tipo en particular. Los atributos se representan como variables y el comportamiento como métodos en una clase Java.

Cualquier instancia creada a partir de la plantilla se denomina un objeto. El proceso a través del cual una instancia (objeto) se crea se llama instanciación.

Se puede modelar el ejemplo de Estudiante, dado anteriormente, en clases y objetos de software.

Se tendrá una clase Estudiante que define atributos como: género, nombre, número de identidad, número de estudiante, carrera estudiante, estatus, nombre, edad, cursos registrados, calificaciones obtenidas y otros.

La Figura 1.1 muestra el modelo de software de un estudiante en una clase Estudiante.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 99

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figure 1.1: Modelo de un Estudiante del Mundo Real como Clase

En la figura anterior, se listan algunos de los atributos de la clase Estudiante. Aquí una variable String se usa para almacenar el nombre del estudiante. El género del estudiante se almacena como carácter (m para indicar masculino y f para indicar femenino). Una variable entera se usa para almacenar la edad del estudiante.

Una vez modelada la clase, se pueden crear cualquier número de objetos de ella. Para crear un objeto de la clase, se necesita un constructor. Un constructor es un método (un método es similar a una función en C o C++), que tiene el mismo nombre de la clase. En el ejemplo anterior, se puede usar el método Estudiante() para crear un objeto de la clase Estudiante, llamado estudiante. El atributo nombre de este objeto será el nombre de estudiante Edna Smith. El código Java que permite hacer esto se muestra a continuación:

Estudiante estudiante = new Estudiante(“Edna Smith”);

Un constructor también inicializa el objeto con valores por defecto, que pueden ser definidos dentro del constructor. Esto se verá en detalle en la sección Constructores de una Clase.

Un objeto creado de esta forma, para representar a la estudiante Edna Smith, se muestra en la Figura 1.2.

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 100

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figure 1.2: Un Objeto de la Clase Estudiante

Se pueden obtener los atributos del objeto estudiante usando los métodos getter (métodos que comienzan con la palabra get, como: getNombre, getEdad, etc.) y se les puede asignar valor a los atributos mediante los métodos setter (métodos que comienzan con la palabra set, como: setNombre, setEdad, etc.).

La Figure 1.3 muestra tres objetos creados de la clase Estudiante para representar tres estudiantes: Edna Smith, J. McDonald and T. Hughes.

Figura 1.3: Objetos Creados de la Clase Estudiante

Estos objetos son diferentes entre sí. Los datos en cada uno de estos objetos son diferentes, aunque las variables en las que se almacenan tengan el mismo nombre. Los métodos que están disponibles en estos objetos son los mismos. De aquí que sean llamadas instancias de la clase.

Se ha visto que una clase tiene variables y métodos. A continuación se presenta la estructura de una clase Java.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 101

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

3. Estructura de una Clase Java Una clase Java consiste de una sentencia package, sentencia import, y una definición de clase. De éstas, las sentencias package e import son opcionales. La sentencia package es la primera sentencia de un programa Java. Se profundizará la definición package en la Unidad 7- Paquetes. La sentencia import va a continuación de la sentencia package. La sentencia import importa otras clases Java que la clase que esta siendo definida puede querer usar. Puede haber más de una sentencia import en el mismo programa Java.

Las otras clases son importadas usando la siguiente sintaxis:

import NombreClase;

Las sentencias import son seguidas por la definición de la clase. De acuerdo a la sintaxis general de una clase, se requiere sólo la palabra reservada class seguida por el nombre de la clase, como sigue:

class NombreClase{

}

Un programa Java puede tener más de una clase. Estas clases pueden estar relacionadas unas con otras. En estos casos, se debe tener una clase con el método main(), para que la ejecución del programa comience con esa clase. Un archivo Java debe tener el mismo nombre que la clase que tenga el método main(), con la extensión .java siempre y cuando esta clase sea declarada como public.

La Figura 1.4 muestra la estructura general de la definición de una clase Java.

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 102

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 1.4: Estructura de Definición de una Clase Java

Habiendo comprendido la estructura de una clase Java, se continúa con los miembros de una clase Java.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 103

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

3.1 Miembros de una Clase Java

Una clase Java tiene variables miembro y métodos miembro. Una clase Java usa modificadores de acceso para otorgar permiso a otras clases para acceder a una variable o método en particular. Un modificador de acceso especifica el acceso a una a variable, método o clase.

Esencialmente, los objetos creados a partir de una clase almacenan sus datos en variables. Un objeto permite que otros objetos tengan acceso a sus datos a través de métodos. Un objeto puede también esconder datos a otros objetos a través de varios modificadores de acceso.

La Figura 1.5 muestra los miembros de una clase.

Figura 1.5: Miembros Principales de una Clase

Se discuten a continuación en las secciones siguientes los miembros principales de una clase, son estos, variables, métodos y modificadores de acceso.

4. Variables Las variables disponibles en una clase pueden ser de varios tipos, son estos, variables de instancia, variables de clase, variables final, variables transient y variables volatile. Observe cada una de ellas en detalle.

4.1 Variables de Instancia

Algunas variables tienen diferentes valores para diferentes instancias de la clase. Estas son llamadas variables de instancia. Por ejemplo, la variable nombre en la clase Estudiante tiene diferentes valores para objetos diferentes, como: Edna Smith, J McDonald and T Hughes. Aquí, nombre es una variable de instancia.

La Figura 1.6 muestra una definición de variables de instancia en una clase Java.

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 104

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

public class Estudiante {

// Variables de Instancia

String nombre;

char genero;

int edad;

}

Figura 1.6: Variables de Instancia en una Clase Java

Las variables de instancia se usan para representar los atributos de datos de un objeto particular. Las variables de instancia son creadas cuando el objeto es instanciado. En la Figura 1.6, nombre, genero y edad son variables de instancia del objeto Estudiante. Estas se acceden usando la instancia o el objeto creado.

4.2 Variables de Clase

En algunas ocasiones es necesario tener una variable que tenga el mismo valor para todas las instancias de la clase. Estas variables se denominan variables de clase. Las variables de clase a veces se les llaman variables static. Sólo habrá una copia de una variable de clase en la memoria independientemente del número de instancias creadas de la clase. Así si el valor es cambiado en alguna instancia, se reflejará en todas las instancias de la clase.

Se usa el modificador static para declarar que una variable es una variable de clase. Para tener acceso a una variable de clase no se necesita crear una instancia de la clase. Se puede acceder a una variable de clase directamente por su nombre junto con el nombre de la clase.

¿Por qué se necesitan variables de clase cuando se puede obtener la misma funcionalidad usando variables de instancia? Puede haber situaciones en las cuales una variable necesita ser especificada como una variable de clase. Por ejemplo, considere una universidad, que asigne un único ID a cada estudiante. El ID de estudiante es un número secuencial, que es almacenado en algún sitio, es incrementado cuando un nuevo estudiante ingresa a la universidad. Una variable llamada maxIdAsignado podría crearse para este caso, maxIdAsignado se mantiene como una variable de clase y se incrementa en el constructor del objeto luego de asignar su valor al ID del estudiante. Así independientemente del número de objetos creados, el máximo ID de estudiante asignado hasta ahora se mantiene como una variable de clase y se incrementa en cada instanciación.

Las variables static son usualmente privadas en la clase.

La Figura 1.7 muestra como una variable de clase es creada y accedida en Java.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 105

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

public class Estudiante {

// Variables de clase

static int maxIdAsignado;

// Variables de Instancia

int id;

// Contructor para la clase Estudiante

public Estudiante() {

this.id = maxIdAsignado++;

}

}

Figura 1.7: Variables de Clase en Java

El valor de maxIdAsignado también podría accederse fuera del ámbito de la clase como se muestra a continuación:

Estudiante.maxIdAsignado++;

Note que aquí se coloca el nombre de la clase seguido por un punto y luego el nombre de la variable de clase. Recuerde que para acceder a las variables de clase no es necesario crear una instancia de la misma.

Java provee valores por defecto para las variables de instancia y las variables de clase. Los valores por defecto son aquellos que son asignados cuando el programador no inicializa explícitamente una variable. Los valores por defecto para los ocho tipos de datos en Java, para variables de clase y de instancia son los siguientes:

boolean false

char (carácter en blanco)

byte 0

short 0

integer 0

long 0

float 0.0

double 0.0

4.3 Variables Volátil (Volatile)

El compilador Java, en tiempo de compilación, realiza muchas optimizaciones para mejorar el desempeño de un programa. El modificador volatile previene al

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 106

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

compilador de realizar ciertas optimizaciones sobre una variable miembro. Le dice al compilador que el valor de la variable puede ser cambiado inesperadamente por otras partes del programa. Esta variable miembro se denomina variable volatile. El compilador, no realiza optimizaciones en estas variables.

Por ejemplo, en un programa multihilos, dos o más hilos pueden compartir la misma variable de instancia. Cada hilo puede tener su propia copia privada de una variable compartida. La copia maestra de la variable reflejará su estado actual. El acceso a la copia maestra debe ser autorizado en el mismo orden en el que se acceden las copias privadas.

El modificador volatile se coloca antes de la declaración de la variable. La sintaxis se muestra a continuación:

volatile int var = 100; 4.4 Variables Transitorias (Transient)

El modificador transient se usa en una declaración de variable para especificar al sistema de tiempo de ejecución de Java que la variable no debe ser serializada. Una variable que no puede ser serializada y que tiene especificado el modificador transient, se denomina variable transient.

La serialización es un proceso mediante el cual, los campos no transient de un objeto son almacenados usando una clase llamada DataOutputStream. El objeto puede ser de-serializado recuperando el dato almacendo usando la clase DataInputStream. La serialización y de-serialización serán tratados en detalle en el Volumen 4, Unidad 3 – Serialización de Objetos.

Un objeto puede tener datos basura, que no son necesarios al momento de reconstruir el objeto desde flujos a través de la de-serialización. Un objeto puede contener ambas variables transient y no transient. Las variables transient se pueden usar para almacenar datos que no serán usados durante el proceso de serialización. Así, los procesos de serialización y de-serialización pueden acelerarse si variables cuyos datos que no se desea serializar se declaran como transient.

La sintaxis para declarar variables transient en Java es la siguiente:

transient int var = 100; 4.5 Variables Final

El modificador final indica que el miembro tiene un valor constante. Un miembro con un valor constante no puede ser modificado. Este tipo de variable se denomina una variable final. En caso de que se trate de cambiar el valor de una variable final en el programa, entonces se generará un error en tiempo de compilación. El nombre de una variable final se representa en letras mayúsculas por convención. Como se muestra aquí:

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 107

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

final float PI = 3.14; Las variables miembro final deben ser inicializadas con un valor en el momento de su declaración. Si no, el compilador arrojará un mensaje de error, diciendo que la variable puede no haber sido inicializada.

El modificador static puede ser combinado con la variable final para declarar constantes de librerías. Esta combinación es particularmente útil al declarar constantes como: PI, E, etc.

La Figura 1.8 muestra el uso de los modificadores final y static para declarar constantes de librerías.

public static final double E = 2.718281828459046;

public static final double PI = 3.141592653589793;

public static final double potencia(double a, double b){...};

public static final long redondear(double a){...};

Figura 1.8: Uso de los Modificadores static and final para Constantes de Librería

A continuación, se va estudiar cómo declarar estas variables.

4.6 Declaración de Variables Miembro

En la clase Estudiante (referirse a la Figura 1.6), vimos que la variable nombre fue declarada como sigue:

public class Estudiante {

private String nombre;

}

Aquí, nombre es declarada como una variable miembro, porque la declaración se hace dentro del cuerpo de la clase y fuera de cualquier método o constructor de la clase. El nombre de la variable miembro es nombre, y su tipo de dato es String. El modificador private indica que nombre como una variable sólo puede ser accedida dentro de los constructors y métodos de la clase Estudiante.

A continuación se examinan los métodos en Java.

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 108

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

5. Métodos Los métodos en Java se usan para tener acceso y manipular las variables. Usualmente, los métodos se usan para asignar, recuperar, o cambiar los valores almacenados en una variable. La definición de métodos establece el tipo y nombre de los parámetros de entrada. Los parámetros pasan a ser variables locales del método, también el método puede declarar otras variables locales dentro de ella. Las variables locales pueden ser de tipo primitivo o referencias a objeto. Ellas no pueden ser referenciadas antes de ser declaradas y no pueden usarse sin haber sido inicializadas. Un ejemplo se presenta a continuación.

public void hacerCualquierCosa() {

MiClase mc;

mc.getNombre(); // Error

mc = new MiClase();

mc.getNombre(); // OK

}

Antes de inicializar mc, no se puede usar mc. El compilador genera un error.

En Java 5.0 se permite establecer un número variable de parámetros en los métodos, al igual que C. Para lograr esto, se hace uso de la expresión .... Seguidamente, se presenta un ejemplo de ello:

public void hacerCualquierCosa(int … args) { for (int arg : args) System.out.println(arg); }

Observe que el identificador args se convierte en un arreglo que contiene los valores que fueron enviados cuando fue invocado el método hacerCualquierCosa().

También se puede combinar el uso de parámetros variables con parámetros no variables, con la restricción de que la declaración del parámetro variable solo se puede hacer al final de la lista de argumentos del método. Se presenta un ejemplo de lo dicho anteriormente:

public void hacerCualquierCosa(String a, int … args) { System.out.println("a: " + a); for (int arg : args) System.out.println(arg); }

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 109

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

En Java, los métodos son de diferentes tipos, son estos, métodos de instancia y métodos de clase. Se verán estos dos tipos en detalle a continuación.

5.1 Métodos de Instancia

Ciertos métodos definidos en una clase operan en variables de instancia de la instancia actual de una clase. Ellos también pueden tener acceso a las variables de clase de esa clase. Estos métodos se denominan métodos de instancia. Las siguientes variables y métodos pueden ser accedidos por un método de instancia:

• Variables de instancia. • Variables de clase. • Otros métodos de instancia. • Métodos de clase.

Un método de instancia, además de realizar otras actividades para la clase, puede obtener y asignar valores a las variables de instancia. Un método getter se usa para obtener el valor de una variable de instancia y normalmente comienza con la palabra get. La Figura 1.9 muestra como el método getter se usa para recuperar el valor almacenado en la variable nombre.

public String getNombre(){

return nombre;

}

Figura 1.9: Método Getter para Recuperar el Valor de una Variable de Instancia

Un método setter se usa para asignar valor a variables privadas. Los métodos setter se inician con la palabra set. La Figura 1.10 muestra como el método setter se usa para asignar valor a la variable nombre.

public void setNombre(String nuevoNombre){

nombre = nuevoNombre;

}

Figura 1.10: Método Setter Que Asigna un Valor a una Variable de Instancia

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 110

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

5.2 Métodos de Clase

Otros métodos definidos en la clase operan solo en variables de clase. Se pueden invocar éstos métodos directamente usando el nombre de la clase sin necesidad de crear una instancia. Estos métodos se conocen como métodos de clase o métodos estáticos. Por ejemplo, un método de clase miMetodoDeClase() de MiClase puede ser invocado como:

MiClase.miMetodoDeClase()

El modificador static se usa en la declaración del método de clase. Para acceder a un método de clase, no se necesita crear una instancia de la clase. Se puede acceder al método de clase directamente. Un método de clase no puede acceder a variables de instancia o métodos de instancia. Acceder a variables o métodos no estáticos desde un método estático genera un error en tiempo de compilación, aunque un método de clase puede ser accedido a través de una instancia.

La librería Math y las clases envolventes (wrapper) tienen varios métodos estáticos. La Figura 1.11 muestra el uso del método estático parseInt definido en la clase Integer.

int radio = Integer.parseInt("6");

//parseInt() es un metodo de la clase Integer

double circunferencia = 2 * radio * Math.PI;

//PI es una constante (variable de la clase puplica Math)

Figura 1.11: Uso del Método Estático parseInt()Definido en la Clase Integer

La clase Math tiene muchas funciones de librería, que también están definidas como métodos estáticos. Así, los métodos definidos en la clase Math pueden usarse directamente. La Figura 1.12 muestra el uso de métodos estáticos definidos en la clase Math.

double valores[] = {11.5, 12.5, -12.5, -13.5};

for(int i=0; i<valores.length; i++){

double actual = valores[i];

System.out.println("Valor: "+actual);

System.out.println("Redondeo hacia arriba: "+Math.ceil(actual));

System.out.println("Redondeo hacia abajo: "+Math.floor(actual));

System.out.println("Redondeo: "+Math.round(actual)+"\n");

}

Figura 1.12: Uso de Métodos Estáticos Definidos en la Clase Math

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 111

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Cuando un usuario inicia una aplicación, algún código debe ser ejecutado. Sin una referencia a objetos, no habrá código a ser ejecutado. Java supera esto proveyendo el método main, que es un método estático. Este método estático main es independiente de un objeto. Dentro del método main, otros objetos pueden ser instanciados.

A continuación se aprenderá a cómo usar los métodos de clase para acceder a la clase.

5.3 Uso de Métodos de Clase para Acceder a la Clase

Cuando una declaración de un método tiene el modificador static, indica que el método es un método de clase y no un método de instancia. Un método de instancia solamente se puede usar cuando se crea un objeto. Un método de clase se puede usar independientemente del objeto. No se tiene que instanciar la clase para usar sus métodos estáticos, pueden ser invocados directamente sin ninguna referencia a un objeto de la clase. El método main de la clase es un método estático, y debe ser usado antes de que cualquier objeto de la clase sea creado. Los métodos estáticos solo pueden invocar otros métodos estáticos

Si el constructor de una clase se declara como private, no se puede crear un objeto de la clase. En este caso, se puede acceder a métodos estáticos para usar los métodos y variables disponibles en la clase. Sea el Ejemplo 1.1, que muestra como los métodos estáticos se pueden usar en un programa Java.

Ejemplo 1.1

El siguiente código muestra el uso de métodos estáticos.

El código Java comienza aquí...

1. /*Definicion de la clase StaticEjemplo comienza aqui*/

2. public class StaticEjemplo {

3. static int n;

4.

5. /*El metodo agregar comienza aqui */

6. static public void agregar(int j, int k) {

7. n = j + k;

8. System.out.println(n);

9. }/* El metodo agregar termina aqui */

10. 11. /*El metodo main comienza aqui */ 12. public static void main(String[] args) { 13. agregar(53, 74); 14. }/* El metodo main termina aqui */ 15. }/*Definicion de la clase StaticEjemplo termina aqui*/

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 112

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

El código Java termina aquí

En la clase anterior, se puede acceder directamente al método agregar() de la clase StaticEjemplo sin crear un objeto de la clase ya que el método agregar() ha sido declarado como estático. Dentro del método agregar, se suman dos enteros pasados como argumentos y se almacena en una variable estática n de la clase. Finalmente se imprime el valor de n en la salida estándar.

Fin del Ejemplo 1.1

Si el método agregar() en el ejemplo anterior fuese declarado como público, podría ser accedido desde otras clases como se muestra a continuación:

StaticEjemplo.agregar();

No hay necesidad de crear un objeto StaticEjemplo para invocar al método estático.

Antes de concluir la discusión de métodos en Java, se resume brevemente como Java permite a los programadores trabajar con los siguientes tipos de métodos, que son usados para propósitos específicos:

• Métodos Abstractos. • Métodos Final. • Métodos Nativos. • Métodos Sincronizados.

Aunque los métodos abstractos son métodos de instancia, los otros tres pueden ser métodos de instancia o de clase.

5.4 Métodos Abstractos

El modificador abstract se usa para denotar que la implementación de un método no está en la clase en la cual el método es declarado. Este método es llamado método abstracto. Los métodos abstractos son declarados solo dentro de una clase abstracta (una clase declarada con el modificador abstract) como se muestra a continuación:

public abstract int mostrarSalida(int a);

A continuación se discuten los métodos final, que son los que no pueden ser sobrescritos por una subclase.

5.5 Métodos Final

Una clase puede heredar variables y métodos definidos en otra clase. La clase desde la cual las variables y métodos son heredados se denomina superclase. La clase que hereda se denomina subclase. Una subclase puede proveer una implementación diferente para un método heredado de su superclase. Esto se conoce como sobre

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 113

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

escritura de método. Si no se quiere que un método sea sobreescrito por sus subclases, se puede usar el modificador final en la declaración del método, como sigue:

public final int mostrarSalida(int a);

A continuación se discute acerca de los métodos nativos, que permiten que se use el código escrito en otro lenguaje.

5.6 Métodos Nativos

Cuando se quiere usar una librería de funciones escritas en otro lenguaje como C o C++, se usa el modificador native para especificar que la implementación de este método no fue hecha en Java.

public native int mostrarSalida(int a);

A continuación se discuten los métodos sincronizados, que juegan un papel fundamental en aplicaciones multihilos.

5.7 Métodos Sincronizados

En un ambiente multihilos, varios hilos pueden estar operando sobre los mismos datos simultáneamente. Los métodos que se usan para operar sobre los mismos datos simultáneamente se declaran como synchronized, para asegurar que la información accedida por los hilos está controlada y realizada a salvo de hilos.

public synchronized int mostrarSalida(int a);

Se ha visto el uso de los modificadores public y private en algunos de los ejemplos anteriores, estos son modificadores de acceso. Se discuten a continuación.

6. Modificadores de Acceso Se pueden usar los modificadores de acceso de Java para proteger las variables y métodos de una clase de ser accedidos sin garantía por parte de otras clases. Los modificadores de acceso permitidos por Java son: public, protected, package y private. Se va a iniciar la revisión con el modificador de acceso public.

6.1 El Modificador de Acceso public

El modificador public no coloca ninguna restricción en las variables y métodos de una clase. Cuando las variables y métodos de una clase son declarados como public, los objetos de cualquier clase pueden accederlos. La clase que esta haciendo el acceso no necesita ser una subclase de la clase accedida o estar presente en el mismo paquete que la clase accedida. Una clase sin ninguna relación, que está en un paquete diferente, puede también acceder a variables y métodos public de una clase. Se debe tener cuidado antes de declarar una variable o método como public para asegurar que no habrá ningún acceso malicioso por parte de un objeto de una clase externa, que

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 114

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

pueden colocar a los objetos de la clase accedida en un estado inconsistente. Considere el Ejemplo 1.2, que ilustra el uso de variables y métodos public.

Ejemplo 1.2

La clase PublicEjemplo que se muestra a continuación tiene una variable y un método public.

El código Java comienza aquí...

1. package miPaquete; 2. /*Definicion de la clase PublicEjemplo comienza aqui*/

3. public class PublicEjemplo {

4. public int secretoAbierto;

5. public void abrirMetodoSecreto() {

6. System.out.println("abrirMetodoSecreto");

7. }

8. }/*Definicion de la clase PublicEjemplo termina aqui*/

El código Java termina aquí

Se va a escribir una clase llamada ClaseNoRelacionada en otroPaquete, que es totalmente diferente del paquete en el cual está la clase PublicEjemplo.

El código Java comienza aquí...

1. package otroPaquete;

2.

3. import miPaquete.*;

4.

5. //Definicion de la clase ClaseNoRelacionada comienza aqui

6. class ClaseNoRelacionada {

7. void accesoSecreto() {

8. PublicEjemplo pe = new PublicEjemplo();

9. pe.secretoAbiert = 35;

10. pe.abrirMetodoSecreto();

11. }

12. }//Definicion de la clase ClaseNoRelacionada termina aqui

El código Java termina aquí

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 115

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

La clase ClaseNoRelacionada no tiene ninguna relación con (no es una subclase de) la clase PublicEjemplo. A pesar de esto, se puede acceder a la variable y al método public definidos en la clase PublicEjemplo.

Fin del Ejemplo 1.2

A continuación se discute el modificador de acceso protected, que no es tan permisivo como el modificador de acceso public.

6.2 El Modificador de Acceso protected

Este modificador permite que variables y métodos de una clase en particular sean accedidas por la clase en la que están definidas, sus subclases y las clases presentes en el mismo paquete. Por ejemplo, se puede querer que cierta información sea compartida solo por nuestra familia o amigos cercanos. No se quiere que nadie más sepa acerca de esto. Cuando se representa este tipo de información como objetos de software creados usando Java, el modificador protected puede ser usado. Esto se explica en el Ejemplo 1.3.

Ejemplo 1.3

Considere el siguiente ejemplo de la clase ProtectedEjemplo. Tiene una variable protected y un método protected.

El código Java comienza aquí...

1. package miPaquete;

2.

3. /*Definicion de la clase ProtectedEjemplo comienza aqui*/

4. public class ProtectedEjemplo {

5. protected int secretoFamiliar;

6. protected void metodoSecretoFamiliar() {

7. System.out.println("metodoSecretoFamiliar");

8. }

9. }/*Definicion de la clase ProtectedEjemplo termina aqui*/

El código Java termina aquí

Ahora, considere la clase ProtectedHijo, que extiende de la clase ProtectedEjemplo, pero que está presente en un paquete otroPaquete que es diferente del paquete en el cual ProtectedEjemplo fue declarada. En este caso, la clase ProtectedHijo implícitamente obtiene todos los métodos definidos en ProtectedEjemplo, pero la clase ProtectedHijo no puede acceder la variable protected o invocar al método protected de un objeto de la clase ProtectedEjemplo. Observe:

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 116

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

El código Java comienza aquí...

1. package otroPaquete;

2.

3. import miPaquete.*;

4.

5. //Definicion de la clase ProtectedHijo comienza aqui

6. class ProtectedHijo extends ProtectedEjemplo {

7. void accederSecreto(ProtectedEjemplo pe, ProtectedHijo ph) {

8. pe.secretoFamiliar = 53; // error

9. ph.secretoFamiliar = 33;

10. pe.metodoSecretoFamiliar(); // error 11. ph.metodoSecretoFamiliar(); 12. } 13. }//Definicion de la clase ProtectedHijo termina aqui

El código Java termina aquí

Ahora se va a considerar otra clase AmigoDeLaFamilia que está en el paquete miPaquete y no es una subclase de ProtectedEjemplo.

El código Java comienza aquí...

1. package miPaquete;

2.

3. //Definicion de la clase AmigoDeLaFamilia comienza aqui

4. class AmigoDeLaFamilia {

5. void accederSecreto() {

6. ProtectedEjemplo pe = new ProtectedEjemplo();

7. pe.secretoFamiliar = 53;

8. pe.metodoSecretoFamiliar();

9. }

10. }//Definicion de la clase AmigoDeLaFamilia termina aqui

El código Java termina aquí

Se puede ver que AmigoDeLaFamilia puede acceder legalmente a las variables y métodos protected de ProtectedEjemplo.

Fin del Ejemplo 1.3

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 117

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

6.3 El Modificador de Acceso package

El modificador de acceso package se usa cuando no se especifica ni public, ni protected, ni private como nivel de acceso. Si no se especifica el nivel de acceso de una variable o un método o una clase usando un modificador de acceso, entonces, por defecto, el nivel de acceso se asume como package. Esto significa que todas las clases que están presentes en el mismo paquete pueden acceder a las variables y métodos de la clase accedida. Un paquete es similar a un módulo. Ada fue uno de los primeros lenguajes en introducir el concepto de un paquete en los lenguajes de programación.

Considere el Ejemplo 1.4, que ilustra el modificador de acceso package.

Ejemplo 1.4

La clase PackageEjemplo que se muestra a continuación tiene una variable y un método con acceso package.

El código Java comienza aquí...

1. package miPaquete; 2.

3. /*Definicion de la clase PackageEjemplo comienza aqui*/

4. public class PackageEjemplo {

5. int secretoEntreAmigos;

6. void metodoSecretoEntreAmigos(){

7. System.out.println("metodoSecretoEntreAmigos");

8. }

9. }/*Definicion de la clase PackageEjemplo termina aqui*/

El código Java termina aquí

La clase PackageEjemplo tiene acceso a la variable secretoEntreAmigos y al método metodoSecretoEntreAmigos(). Todas las clases presentes en el paquete miPaquete tienen acceso a la variable secretoEntreAmigos y al método metodoSecretoEntreAmigos().

Ahora, considere la clase PackageAmigo, que está presente en miPaquete.

El código Java comienza aquí...

1. package miPaquete;

2.

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 118

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

3. /*Definicion de la clase PackageAmigo comienza aqui*/

4. class PackageAmigo{

5. void accederSecretoPackage(){

6. PackageEjemplo pe = new PackageEjemplo();

7. pe.secretoEntreAmigos = 25;

8. pe.metodoSecretoEntreAmigos();

9. }

10. }/*Definicion de la clase PackageAmigo termina aqui*/

El código Java termina aquí

La clase PackageAmigo puede acceder a secretoEntreAmigos y metodoSecretoEntreAmigos porque PackageAmigo y PackageEjemplo están en el mismo paquete.

Considere el siguiente código.

El código Java comienza aquí...

1. package otroPaquete;

2.

3. import myPackage.*;

4.

5. /*Definicion de la clase PackageHijo comienza aqui*/

6. class PackageHijo extends PackageEjemplo {

7. void accederMiembrosDePackage(){

8. PackageEjemplo pe = new PackageEjemplo();

9. pe.secretoEntreAmigos = 25; // error

10. pe.metodoSecretoEntreAmigos(); // error 11. } 12. }/*Definicion de la clase PackageHijo termina aqui*/

El código Java termina aquí

El código anterior muestra que si hay una subclase de PackageEjemplo en un paquete diferente, entonces no podrá acceder a secretoEntreAmigos o metodoSecretoEntreAmigos de PackageEjemplo.

Fin del Ejemplo 1.4

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 119

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

A continuación se discute el modificador de acceso private, que es el más restrictivo de todos los modificadores de acceso.

6.4 El Modificador de Acceso private

El modificador de acceso private se usa para proteger información muy confidencial. Puede haber ocasiones cuando no se quiere que métodos o variables de una clase en particular accedan a ciertas variables o métodos de otra clase específica. Usando variables y métodos privados en una clase se provee la máxima protección. Esto se explica en el Ejemplo 1.5.

Ejemplo 1.5

Aquí la clase NivelAccesoEjemplo tiene una variable private y un método private.

El código Java comienza aquí...

1. /*Definicion de la clase NivelAccesoEjemplo comienza aqui*/

2. public class NivelAccesoEjemplo {

3. private int secreto;

4. private void metodoSecreto(){

5. System.out.println("metodoSecreto");

6. }

7. }/*Definicion de la clase NivelAccesoEjemplo termina aqui*/

El código Java termina aquí

Sólo el código dentro de la clase NivelAccesoEjemplo puede leer o modificar la variable secreto e invocar metodoSecreto(). El código dentro de otra clase no puede acceder o modificar la variable secreto o invocar a metodoSecreto(). Por ejemplo, la clase Hacker, definida a continuación, no puede acceder a secreto o a metodoSecreto de NivelAccesoEjemplo.

El código Java comienza aquí...

1. /*Definicion de la clase Hacker comienza aqui*/

2. class Hacker {

3. public static void main(String[] args) {

4. NivelAccesoEjemplo nae = new NivelAccesoEjemplo();

5. nae.secreto = 364; // error

6. nae.metodoSecreto(); // error

7. }

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 120

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

8. }/*Definicion de la clase Hacker termina aqui*/

El código Java termina aquí

Cuando se intenta compilar la clase Hacker, el compilador imprimirá un mensaje de error, similar a este:

Hacker.java:4: secreto has private access in NivelAccesoEjemplo

nae.secreto = 364; // error

^

Hacker.java:5: metodoSecreto() has private access in NivelAccesoEjemplo

nae.metodoSecreto(); // error

^

2 errors

Nota: Un objeto del tipo NivelAccesoEjemplo puede acceder a los miembros private de otro objeto de NivelAccesoEjemplo. Esto se muestra en el siguiente fragmento de código:

El código Java comienza aquí...

1. /*Definicion de la clase PrivateEjemplo comienza aqui*/

2. class PrivateEjemplo {

3. private int secreto;

4. boolean verificarAccesoPrivado(PrivateEjemplo pe){

5. if (this.secreto == pe.secreto)

6. return true;

7. else

8. return false;

9. }

10. }/*Definicion de la clase PrivateEjemplo termina aqui*/

El código Java termina aquí

En este caso, la clase PrivateEjemplo tiene un método de instancia que compara el objeto actual PrivateEjemplo (this) con otro objeto PrivateEjemplo pe, basado en sus variables secreto. Esto es posible porque objetos del mismo tipo pueden acceder a miembros private del otro siempre y cuando estén dentro de la clase.

Fin del Ejemplo 1.5

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 121

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Se van a discutir a continuación los constructores en Java.

7. Constructores de una Clase Un constructor se usa esencialmente para inicializar un nuevo objeto creado de un tipo en particular. Se puede identificar fácilmente el constructor y diferenciarlo de otros métodos en la clase porque el constructor tiene el mismo nombre de la clase. Los constructores también son métodos, pero están definidos para realizar la tarea de inicialización al momento de creación de objetos.

Todas las clases en Java tienen al menos un constructor. Si el programador no define ningún constructor para una clase, entonces la clase tendrá un constructor por defecto creado por el sistema de tiempo de ejecución de Java. El constructor por defecto no acepta ningún argumento. Tiene una implementación vacía y no realiza nada.

Java permite tener tantos constructores como se requiera para una clase, la única diferencia será en el número o el tipo de argumentos para una clase. Esto se denomina sobrecarga del constructor, que será discutida en detalle en la próxima sección.

La Figura 1.13 muestra los constructores para la clase Student. Se definen tres constructores, cada uno toma diferentes parámetros.

public Estudiante(){}

public Estudiante(int nuevoId){

id = nuevoId;

}

public Estudiante(int nuevoId, String nuevoNombre){

id = nuevoId;

nombre = nuevoNombre;

}

Figura 1.13: Constructores para la Clase Estudiante

Si el programador define un constructor para una clase, el constructor por defecto no estará disponible para la clase. Si una clase necesita un constructor que no acepte argumentos, el programador debe explícitamente definir un constructor sin argumentos. En la clase Estudiante anterior, se proveen los constructores Estudiante(int), Estudiante(int, String), por esto el constructor por defecto sin argumentos no estará disponible, y se encontrará el constructor Estudiante() sin parámetros explícitamente definido.

Se va a considerar otro ejemplo para entender mejor los constructores en Java. Para una clase llamada Fibonacci, se tiene el siguiente constructor:

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 122

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

public Fibonacci() { // constructor

n = 0;

}

Este es un ejemplo de un constructor sin argumentos. Se va a definir otro constructor para Fibonacci:

public Fibonacci(int numeroDeTerminos) { // constructor

n = numeroDeTerminos;

}

Ambos constructores tienen el mismo nombre, la única diferencia es la lista de parámetros aceptada por estos constructores. El compilador los diferencia dependiendo del número y tipos de argumentos que aceptan. El primer constructor no acepta ningún parámetro, mientras que el segundo constructor acepta un argumento de tipo int .

Usualmente el constructor usa sus argumentos para inicializar las variables (estado) del nuevo objeto creado. Cuando se instancia una clase para crear un objeto, se debe escoger el constructor cuyos argumentos reflejen mejor la forma en que se quiere inicializar el nuevo objeto. Dependiendo del número de argumentos y el tipo de argumentos que se pasa al constructor, el compilador busca el constructor apropiado para usarlo. Por ejemplo, cuando se usa el siguiente código, el compilador sabe que debe elegir el constructor sin argumentos.

new Fibonacci();

De manera similar, cuando se usa la expresión new Fibonacci(53); el compilador escoge el constructor que acepta un sólo entero como su argumento.

El código que se presenta a continuación invoca el constructor de la superclase de la clase Fibonacci.

void Fibonacci() {

super();

}

No se ha hecho a Fibonacci una subclase de otra clase. Por defecto, todas las clases creadas en Java son subclases de la clase Object disponible en el paquete java.lang. Así, en el código anterior, el constructor de la clase Object es invocado. Usualmente el constructor de una clase toma ventaja del código proporcionado en el constructor de su superclase. Suponga que se quiere usar el constructor de la superclase, entonces la sentencia que invoca al constructor de su superclase debe ser la primera sentencia de su constructor, debido a que debe realizar primero un nivel superior de inicialización.

De la discusión en esta sección, se puede ver que en la declaración de una clase, es obligatorio especificar la palabra reservada class y también el nombre de la clase. El resto de los componentes de una declaración de clase son opcionales. Si una

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 123

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

declaración de clase no tiene estos elementos opcionales, los valores por defecto que usa el compilador Java son: no-public, no-final, no-abstract y sub-clase de la clase Object. La clase java.lang.Object es la superclase de todas las clases Java por defecto. Se estudiará en detalle super clases en la Unidad 3 - Herencia de este volumen. El compilador Java también asume que una clase no implementa ninguna interfaz. Considere el Ejemplo 1.6, un programa que imprime los primeros cinco términos de la serie de Fibonacci.

Ejemplo 1.6

Se va a crear una clase en este programa de ejemplo. Se usará esta clase en las siguientes secciones.

El código Java comienza aquí...

1. /*Definicion de la clase Fibonacci comienza aqui*/ 2. public class Fibonacci {

3. public int a = 0, n; /* variable */

4. private int b = 1, c, contador = 2; /* variables */

5.

6. /* Constructor Fibonacci comienza aqui */

7. public Fibonacci(int numeroDeTerminos) {

8. n = numeroDeTerminos;

9. }/* Constructor Fibonacci termina aqui */

10. 11. /* Metodo cambiarNumeroDeTerminos comienza aqui */ 12. void cambiarNumeroDeTerminos(int numeroDeTerminos) { 13. n = numeroDeTerminos; 14. }/* Metodo cambiarNumeroDeTerminos termina aqui */ 15. 16. /* Metodo mostrarSeries comienza aqui */ 17. public void mostrarSeries() { 18. if (n <= 0) { 19. System.out.println("Entrada invalida"); 20. System.exit(0); 21. } 22. if (n >= 1) 23. System.out.println(a); 24. if (n >= 2) 25. System.out.println(b); 26. while (contador < n) {

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 124

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

27. c = a + b; 28. System.out.println(c); 29. a = b; 30. b = c; 31. contador++; 32. } 33. }/* Metodo mostrarSeries termina aqui */ 34. 35. /* Metodo main comienza aqui */ 36. public static void main(String args[]) { 37. Fibonacci fib = new Fibonacci(5);// 5 términos 38. fib.mostrarSeries(); 39. }/* Metodo main termina aqui */ 40. }/* Definicion de la clase Fibonacci termina aqui */

El código Java termina aquí

Este programa de ejemplo imprime los números de la serie de Fibonacci, hasta el número de términos que son requeridos (cinco, en este caso). El número de términos de la serie a ser impresos se pasa como argumento al constructor. El constructor asigna el parámetro recibido a una variable de instancia n. cambiarNumeroDeTerminos() se usa para cambiar el valor de n, si se desea hacerlo después que el objeto ha sido creado. El método mostrarSeries() se usa para imprimir la serie de números Fibonacci en la salida estándar. Se puede ver que hay dos componentes principales que nos dan la implementación de la clase, que son, la declaración de la clase y el cuerpo de la clase.

La declaración del ejemplo anterior es simple. Indica que el nombre de la clase es Fibonacci y que es una clase public. A veces de la declaración, se puede también identificar la superclase de esa clase y si esta clase puede ser derivada.

Fin del Ejemplo 1.6

Así como los constructores pueden ser sobrecargados, otros métodos también pueden ser sobrecargados en Java. Se va a discutir la sobrecarga de métodos, mediante la cual se pueden tener varias implementaciones para el mismo método.

8. Sobrecarga de Método En la sección anterior se vio que más de un constructor puede ser creado para una clase. De manera similar, Java permite tener dos o más métodos con el mismo nombre dentro de la misma clase. Como con los constructores, los métodos sobrecargados

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 125

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

deben también tener un número diferente de parámetros o diferentes tipos de datos en los parámetros. Esta característica de Java se llama sobrecarga de métodos. Ésta es una forma de lograr polimorfismo en Java. El compilador detectará un error en tiempo de compilación si dos métodos en una clase tienen el mismo nombre y el mismo número y tipo de parámetros.

Los métodos sobrecargados pueden tener diferentes tipos de datos de retorno. Pero si la diferencia entre dos métodos es sólo en cuanto a sus tipos de retorno, el nombre, número, y tipo de argumentos aceptados por el método, y el orden en el cual son aceptados, son iguales, el compilador no distinguirá entre los dos métodos.

Si dos métodos son diferentes solo en sus tipos de retorno, esto no se considera una sobrecarga de métodos. Sin embargo, si existen dos métodos que aceptan el mismo número de argumentos y el mismo tipo de argumentos, pero difieren en el orden de los tipos de datos aceptados por los dos métodos, entonces sí se considera una sobrecarga de métodos.

Ejemplo 1.7

El siguiente programa ilustra la sobrecarga de métodos.

El código Java comienza aquí...

1. /*Definicion de la clase comienza aqui*/

2. public class MetodoSobrecargadoEjemplo {

3. void mostrarEnPantalla(int a, int b){

4. System.out.println(a);

5. System.out.println(b+"\n");

6. }

7.

8. void mostrarEnPantalla(int a, char b){

9. System.out.println(a);

10. System.out.println(b+"\n"); 11. } 12. 13. void mostrarEnPantalla(char a, int b){ 14. System.out.println(a); 15. System.out.println(b+"\n"); 16. } 17. 18. void mostrarEnPantalla(int a, int b, char c){ 19. System.out.println(a); 20. System.out.println(b);

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 126

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

21. System.out.println(c+"\n"); 22. } 23. 24. void mostrarEnPantalla(int a, char b, float c, String d){ 25. System.out.println(a); 26. System.out.println(b); 27. System.out.println(c); 28. System.out.println(d+"\n"); 29. } 30. 31. public static void main(String[] args) { 32. MetodoSobrecargadoEjemplo msce = new 33. MetodoSobrecargadoEjemplo(); 34. msce.mostrarEnPantalla(53,8965); 35. msce.mostrarEnPantalla(68, 'g'); 36. msce.mostrarEnPantalla('f', 74); 37. msce.mostrarEnPantalla(64, 36, 'h'); 38. msce.mostrarEnPantalla(85, 'd', (float) 745.3, "true"); 39. } 40. }/*Definicion de la clase termina aqui*/

El código Java termina aquí

La salida del programa se muestra a continuación:

53

8965

68

g

f

74

64

36

h

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 127

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

85

d

745.3

true

En la salida del programa anterior se puede ver en la línea 37 de la clase MetodoSobrecargadoEjemplo que a pesar que el tercer argumento pasado al método fue el carácter ‘h’, ese carácter no se imprimió y que en su lugar se imprimió el valor ASCII del carácter, que es 104. Esto se debe a que el compilador primero busca por la correspondencia exacta de ambos, tanto del número de argumentos como del tipo de dato de los argumentos.

En un programa, cuando ambas condiciones corresponden con una versión sobrecargada particular del método, se llama a esa versión particular del método. En la ausencia de tal correspondencia, el compilador convierte implícitamente el tipo de dato de los argumentos a algún otro tipo de dato, siempre que esa conversión se permita en Java.

En el ejemplo anterior, el compilador busca por una correspondencia exacta para el conjunto de tres tipos de datos. Si se encuentra esa correspondencia, esta versión particular del método sobrecargado será invocada. Sin embargo, no existe una correspondencia directa cuando dos enteros y un carácter son pasados como argumentos. Así que el tercer argumento se convirtió implícitamente a un int (Java permite tal conversión, de int a char y viceversa), hubo una correspondencia con la versión del método mostrarEnPantalla, la cual toma tres enteros como argumentos. Se invocó esa versión y por lo tanto se obtuvo la salida anterior.

Fin del Ejemplo 1.7

A continuación se va a entender el concepto de clases anidadas.

9. Clases Anidadas Una clase anidada es una clase cuya definición está dentro de otra clase. Si una clase contiene a una clase anidada, es conocida como clase exterior.

Las clases anidadas tienen acceso total a los miembros de su clase exterior, incluso a los miembros privados. Estas clases son consideradas miembro de la clase contenedora. Ellas pueden ser final o abstract. Ahora como miembro también puede ser private, protected, además de public o package que es una posibilidad para cualquier clase.

La forma general de una clase exterior que contiene a una clase anidada se muestra a continuación:

class ClaseExterna{

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 128

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

//miembros de ClaseExterna

public static class ClaseAnidadaEstatica {

//miembros de ClaseAnidadaEstatica

}

private class ClaseInterna {

//miembros de ClaseInterna

}

}

Existen dos tipos de Clases Anidadas:

• Clase Anidada Estática: esta clase se declara como miembro estático (static) de la clase exterior y tiene todas las características de cualquier otro miembro estático.

• Clase Interna: Esta clase se declara como miembro no-estático de la clase exterior y tienen todas las características de cualquier otro miembro de instancia. Una instancia de alguna clase interna sólo puede existir si una instancia de la clase contenedora existe. La clase interna no puede tener miembros estáticos propios.

Un ejemplo de clase anidada se muestra a continuación:

Ejemplo 1.8

El siguiente programa ilustra una clase anidada.

El código Java comienza aquí...

1. /*Definicion de la clase Carro comienza aqui*/

2. public class Carro {

3. private String marca;

4. private int velocidadActual;

5. private String placa;

6. private String nombre;

7.

8. /* Definición de clase anidada */

9. class Acelerador {

10. private int velocidadMaxima; 11. 12. Acelerador() { 13. velocidadMaxima = 180; 14. }

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 129

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

15. 16. public void acelerar(int velocidad) { 17. if ((velocidad + velocidadActual) < velocidadMaxima){ 18. velocidadActual = velocidadActual + velocidad; 19. } 20. } 21. 22. public void imprimirVelocidad() { 23. System.out.println("Velocidad: " + velocidadActual); 24. } 25. }/* Fin de la clase anidada Acelerador */ 26. 27. /* Constructor Carro comienza aqui */ 28. Carro(String mar, String nom, String pla) { 29. marca = mar; 30. nombre = nom; 31. placa = pla; 32. velocidadActual = 0; 33. }/* Constructor Carro termina aqui */ 34. 35. /* Metodo main comienza aqui */ 36. public static void main(String[] args) { 37. Carro miCarro = new Carro("Ford", "Focus", "KAA-87X"); 38. Acelerador miAcelerador = miCarro.new Acelerador(); 39. miAcelerador.acelerar(100); 40. miAcelerador.imprimirVelocidad(); 41. }/* Metodo main termina aqui */ 42. }/* Definicion de la clase Carro termina aqui */

El código Java termina aquí Note que en la línea 38 se necesita la instancia de la clase Carro para poder crear una instancia de Acelerador, debido a que esta última es un miembro de instancia de la clase Carro. Fin del Ejemplo 1.8 Una clase interna también puede estar definida dentro de algún método de una clase externa. Esta representación es como sigue:

public class ClaseExterna{

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 130

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

int x;

public void metodoExterno(final int y){

final int z=12;

class ClaseInterna{

public void metodoInterno(){

x=3-y+z;

System.out.println(x);

}

}

}

}

Este tipo de clase interna puede acceder a todos los miembros de la clase contenedora, inclusive puede modificarlos. Sin embargo sólo tiene acceso a las variables final del método que la contiene, en el ejemplo, ‘y’ y ‘z’.

Es posible declarar clases internas con o sin nombre. Las clases internas sin nombre son conocidas como Clases Internas Anónimas y serán discutidas para el manejo de eventos en la Unidad 5 – Modelo de Delegación de Eventos y Manejo de Eventos del Volumen 5. A continuación se va a entender cómo tomar entradas del usuario a través de argumentos de la línea de comandos.

10. Argumentos de Línea de Comandos Los argumentos de línea de comandos se pueden usar para suministrar entradas a un programa durante su ejecución. La construcción general para los argumentos de línea de comandos es como sigue:

java nombreClase argumento1 argumento2 etc…

Se pueden dar cualquier número de argumentos de línea de comandos. Estos argumentos de línea de comando se guardan en un arreglo de string pasado al método main().

Ejemplo 1.9

El siguiente programa ilustra el uso de los argumentos de línea de comandos:

El código Java comienza aquí...

1. /*Definicion de la clase comienza aqui*/

2. public class LineaDeComandosEjemplo {

3. public static void main(String[] args) {

4. for (int i = 0; i < args.length; i++) {

5. System.out.print("Argumento " + (i+1));

6. System.out.print(" es args[" + i + "]");

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 131

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

7. System.out.println(": " + args[i]);

8. }

9. }

10. }/* Definicion de la clase termina aqui */

El código Java termina aquí

El programa se ejecuta como sigue:

java Estos son argumentos pasados por linea de comandos

La salida del programa se muestra a continuación.

Salida:

Argumento 1 es args[0]: Estos

Argumento 2 es args[1]: son

Argumento 3 es args[2]: argumentos

Argumento 4 es args[3]: pasados

Argumento 5 es args[4]: por

Argumento 6 es args[5]: linea

Argumento 7 es args[6]: de

Argumento 8 es args[7]: comandos

Fin del Ejemplo 1.9

Todos los argumentos de la línea de comandos son interpretados como strings en Java. El programador puede usar las funciones de conversión para convertirlos a sus valores numéricos usando los métodos proporcionados en la clase String.

A continuación se discuten las diferentes etapas en el ciclo de vida de un objeto.

11. Ciclo de Vida de un Objeto Usualmente, en un programa Java, se crean objetos de varias clases. Estas clases interactúan entre sí a través de mensajes. Una vez que se completa el objetivo para el cual fue creado el objeto, está listo para recolección como basura. Una vez que el recolector de basura toma el objeto, los recursos que mantenía son liberados, para permitir que otros objetos puedan hacer uso de ellos. El objeto es entonces destruido.

La Figura 1.14 muestra el ciclo de vida de un objeto.

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 132

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 1.14: Ciclo de Vida de un Objeto

A continuación se verá la creación e instanciación de objetos.

11.1 Crear Objetos

Como se mencionó anteriormente, el proceso de crear objetos de una clase se denomina instanciación. El objeto de una clase se conoce como instancia. Tome de nuevo el Ejemplo 1.6. Se puede usar el operador new para instanciar una clase, como sigue:

Fibonacci fib = new Fibonacci();

El código anterior realiza tres acciones, son estas, declaración del objeto, instanciación del objeto e inicialización del objeto. La declaración del objeto y la instanciación del objeto pueden realizarse en pasos separados, como se muestra a continuación.

Fibonacci fib;

fib = new Fibonacci();

Aquí, la primera línea es la declaración del objeto y la segunda, línea la instanciación del objeto. La segunda línea usa el operador de instanciación new para crear un nuevo objeto del tipo Fibonacci. La inicialización del objeto se hace usando la parte de código después del operador new, es decir, Fibonacci(). Esta parte del código invoca al constructor de la clase Fibonacci, que efectúa la inicialización.

Java permite usar clases e interfaces en forma similar para tipos de datos. Esto es posible dado que ambos son tipos referencia. En la etapa de declaración, se crea una variable que puede guardar los objetos del tipo definido por la clase. En el ejemplo anterior, la variable fib sirve para guardar objetos del tipo Fibonacci. Esta variable no puede ser usada para referenciar otro objeto simultáneamente.

El operador new que se usa para instanciar una clase, reserva la memoria requerida pare el nuevo objeto creado. El operador new es seguido por el constructor de la clase instanciada. Al invocar al constructor inicializa el nuevo objeto creado.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 133

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

11.2 Uso de Objetos

Una vez que se crea un objeto de un tipo en particular (clase), se puede usar el objeto para obtener alguna información, cambiar el estado de sus variables, o realizar alguna tarea. Se pueden manipular sus variables a través de los métodos definidos en su clase.

Observe de nuevo la clase Fibonacci del Ejemplo 1.6, se puede modificar el valor de la variable n accediéndola directamente, también se puede modificar el valor de la variable invocando al constructor de la clase.

11.3 Variables Referencia en un Objeto

Hay dos formas de tener acceso a la variable n, que es parte de la instancia de la clase Fibonacci. El primer método es acceder a la variable directamente. La segunda forma es a través de un método (el método cambiarNumeroDeTerminos(), o el constructor). Se examinará la segunda forma de acceder a variables en la próxima sección.

Instanciando la clase Fibonacci como sigue:

Fibonacci fib = new Fibonacci(15);

En este caso, a la variable n se le asigna el valor de 15 por el constructor, porque ha sido implementado para asignar el valor de su argumento a n. Esta es una manera de acceder a la variable, es similar a acceder a variables a través de un método.

Ahora, si se quiere cambiar el valor de la variable n del objeto fib, se puede acceder a ella como sigue:

fib.n = 20;

Esencialmente, la referencia al objeto (fib en este caso), seguida por ‘.’, luego por el nombre de la variable, es la sintaxis usada para acceder a la variable.

En este caso, se tiene la referencia al objeto. Otra forma de acceder a una variable sin que la referencia al objeto sea creada, se muestra a continuación:

int valorN = new Fibonacci(20).n;

Aquí, se crea un nuevo objeto, pero su referencia no es almacenada, porque la referencia no será usada posteriormente.

Las referencias a objetos apuntando al mismo tipo de objetos, no necesariamente tienen el mismo valor en sus variables. Considere las siguientes líneas de código:

Fibonacci fib1 = new Fibonacci(10);

Fibonacci fib2 = new Fibonacci(20);

Aquí, la variable n del objeto fib1 tendrá un valor de 10 (el valor de fib1.n es 10) y la variable n de fib2 tendrá un valor de 20 (el valor de fib2.n es 20).

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 134

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

A continuación se aprenderá a invocar métodos en un objeto.

11.4 Invocando los Métodos de un Objeto

En la sección anterior se estudió cómo se puede cambiar el valor de la variable n accediéndola directamente. En esta sección se presenta cómo lograr lo mismo invocando el método disponible en el objeto de la clase. Considere la misma clase Fibonacci del Ejemplo 1.6.

Hay tres formas de asignarle valor a n. Una forma es cuando se instancia el objeto. Se puede asignar un valor entero a la variable n pasándole un valor entero como un argumento al constructor.

Una vez que el valor ha sido asignado a la variable usando el constructor, la segunda forma de poder cambiar el valor de la variable n, es accediéndola directamente; la tercera forma es invocando a un método de la clase que permita cambiar el valor de n.

El método cambiarNumeroDeTerminos() es un método provisto por la clase Fibonacci para modificar el valor de n. Un valor entero es pasado como argumento del método, y se asigna como el nuevo valor para n.

Fibonacci fib = new Fibonacci(10);

fib.cambiarNumeroDeTerminos(64);

Aquí, se crea un objeto del tipo Fibonacci y se tiene la variable fib como la referencia al objeto creado. En la siguiente sentencia, mediante la referencia al objeto accedemos al método cambiarNumeroDeTerminos() del objeto, y se pasa 64 (un valor entero) como argumento del método. Este método asigna el valor 64 a la variable n del objeto. Se accede al método dentro del objeto en forma similar a la que se usa para acceder las variables del objeto.

Primero, se obtiene la referencia al objeto. En este ejemplo, fib es la referencia al objeto Fibonacci. Después del nombre de la referencia, se usa el nombre del método seguido por su lista de argumentos, con un punto entre la referencia al objeto y el nombre del método. En caso de que el método no tome argumentos, se usa la referencia seguida por el nombre del método, con un punto entre ellos. Los paréntesis que abren y cierran () deben seguir al nombre del método. Estos para indicar que el nombre que le sigue a la referencia al objeto es de un método y no de una variable.

Como en el caso de las variables, para acceder a los métodos de un objeto también se puede usar una expresión que retorne una referencia a un objeto, seguida por el nombre del método con un punto entre ellos, como se muestra a continuación:

new Fibonacci(10).cambiarNumeroDeTerminos(64);

Se puede llamar al método printSeries() del objeto Fibonacci directamente, para imprimir 10 términos de la serie de números Fibonacci como se muestra a continuación:

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 135

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

new Fibonacci(10).mostrarSeries();

El método mostrarSeries() no retorna ningún valor (indicado por la palabra clave void). Suponga que se tiene un método que retorna un valor y se quiere guardar el valor retornado, se puede hacer como se muestra a continuación:

(Asuma que el método mostrarSeries() retorna un valor entero).

El código Java comienza aquí...

public int mostrarSeries() { // método

if(n<=0) {

System.out.println("Entrada invalida");

return(0);

}

if(n>=1)

System.out.println(a);

if(n>=2)

System.out.println(b);

while(contador<n) {

c=a+b;

System.out.println(c);

a=b;

b=c;

contador++;

}

return(1);

}

El código Java termina aquí

En el caso anterior el método mostrarSeries() retorna 1 para indicar que la operación fue exitosa, o 0 para indicar lo contrario. Si se quiere guardar el valor retornado por el método en una variable, se hace como sigue:

int exito = new Fibonacci(10).mostrarSeries();

o

Fibonacci fib = new Fibonacci(10);

int exito = fib.mostrarSeries();

En el segundo caso, la referencia al objeto Fibonacci debe ya estar disponible en la variable fib como se discutió anteriormente en esta sección. Invocar un método en un objeto es similar a enviar un mensaje a ese objeto. Si se tienen dos variables de

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 136

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

referencia (digamos, fib y fib1) apuntando a diferentes objetos de la misma clase Fibonacci, invocar el mismo método en ambos objetos puede retornar resultados diferentes.

int exito = fib.mostrarSeries();

int exito1 = fib1.mostrarSeries();

En este caso, exito y exito1 pueden tener diferentes valores, debido a que fib y fib1 son referencias a diferentes objetos de la misma clase.

A continuación se discute el manejo de la memoria en Java.

12. Manejo de la Memoria en Java En Java, la memoria se asigna cuando un objeto es creado a partir de una clase. Java da soporte a un manejo de memoria automático. Esto significa que la memoria asignada a un objeto está disponible para este, mientras el objeto este siendo usado en el programa Java. Después que el objeto se usa en un programa, el recolector de basura lo reclama y la memoria asignada a éste es liberada.

A continuación se estudia el recolector de basura en detalle.

12.1 El Recolector de Basura

Para usar un objeto en un programa Java, se necesita una referencia al objeto. Una referencia al objeto se usa para encapsular la referencia de los nuevos objetos creados. Se puede usar esta referencia para examinar y manipular al objeto.

El recolector de basura es un hilo de baja prioridad que se mantiene ejecutando en segundo plano en una JVM. Se mantiene revisando que un objeto sea alcanzable por cualquier tipo de referencia. Un objeto es alcanzable si es accesible en el programa. Un objeto que está actualmente en uso en un programa es accesible por alguna parte del programa en su etapa actual de ejecución. Cuando el objeto se torna inalcanzable por cualquier tipo de referencia, es reclamado para destrucción. La memoria asignada al objeto es liberada y puede ser usada por otros objetos. Este proceso es conocido como recolección de basura. En lenguajes de programación como C y C++, la memoria dinámicamente asignada tiene que ser explícitamente liberada. En Java, el recolector de basura se encarga de liberar la memoria no utilizada.

13. Enumeraciones En Java 5.0, aparece la palabra reservada enum que permite definir un conjunto de valores constantes bajo un mismo espacio de nombres que lo hace ser más coherente y legible. Seguidamente, se presenta un ejemplo de ello:

enum Semana {DOMINGO, LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO}

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 137

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

public void diasSemana() { for (Semana dia : Semana.values()) System.out.println(dia); }

13.1 Características de las Enumeraciones

A continuación se presentan las características más relevantes de las enumeraciones:

• Las enumeraciones son clases: Cada constante de enumeración es un objeto del tipo de la clase enumeración.

• Las enumeraciones extienden de java.lang.Enum: Todas las enumeraciones extienden implicitamente de java.lang.Enum. No es posible crear una enumeración que herede de otra clase debido a la definición de la clase Enum:

abstract class Enum<E extends Enum<E>>

• Sus valores no son tipo de datos enteros: Cada valor declarado es una instancia de la clase enumeración en sí mismo.

• No tienen un constructor público: Esto elimina la posibilidad de crear instancias adicionales no definidas en tiempo de compilación. Sólo aquellas instancias definidas por enum están disponibles para su uso.

• Sus valores son public, static y final: Impide que sus valores puedan ser sobreescritos o cambiados. Además, impide que estos objetos sean superclases de otras.

• Sus valores pueden ser comparados con == o equals().

• Las enumeraciones implementan java.lang.Comparable y java.io.Serializable.

• Las enumeraciones definen el método valueOf(): Devuelve el valor de la constante de enumeración basado en el String pasado por parámetro.

• Las enumeraciones proveen el método values(): Retorna un arreglo con la lista de las constantes de la enumeración.

• Las enumeraciones pueden tener constructores, variables de instancia y métodos: Los contructores son llamados automáticamente cuando se declara cada constante de enumeración. Cada constante de enumeración tiene su propia copia de las variables de instancia.

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 138

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Resumen Ahora que ha completado esta unidad, usted debe ser capaz de:

• Explicar los conceptos de clases y objetos. • Discutir acerca de la estructura y miembros de una clase Java. • Definir variables y métodos en Java. • Explicar los modificadores de acceso. • Explicar la necesidad y uso de los constructores de las clases. • Explicar cómo los métodos en una clase Java pueden ser sobrecargados. • Mencionar cómo Java maneja los argumentos de la línea de comandos. • Explicar el ciclo de vida de un objeto. • Describir el manejo de la memoria en Java. • Exponer el uso de Enumeraciones.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 139

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 1: Examen de Autoevaluación 1) Cuando se crea una instancia de una clase, es obligatorio declarar la variable que

será usada para contener la referencia al objeto. a) Verdadero b) Falso

2) Se puede usar el valor de retorno del operador new para acceder a las variables

del objeto recién creado como sigue: new Fibonacci(10).n;

a) Verdadero b) Falso

3) Para una clase llamada MiClase, ¿cuál de las siguientes es la forma correcta de

definir un constructor sin argumentos? a) int MiClase() {…} b) void MiClase() {…} c) MiClase(int miObjetoDeClase) {…} d) MiClase() {…}

4) ¿Cuál de los siguientes debe estar necesariamente presente en una definición de

una clase? a) Sentencia import b) Nombre de la superclase c) Palabra reservada class d) Interfaces implementadas

5) La clase X está definida en el paquete p1. La clase Y, que es una subclase de X,

está definida en el paquete p2. ¿Qué tipo de variables declaradas en X pueden ser accedidas por un objeto de Y? a) private b) protected c) public d) package

Core Java Guía del Estudiante

Unidad 1: Clases y Objetos Libro 1: Core Java 140

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

6) ¿Cuál de los siguientes tipos de variables en Java no pueden ser serializadas? a) transient

b) volatile

c) final

d) protected

7) ¿Cuál de los siguientes tipos de métodos pueden usar código en C en un programa Java? a) static

b) volatile

c) final

d) native

8) ¿Qué tipo de método puede invocar un método estático? a) final b) volatile c) private d) static

9) ¿Es posible para una clase tener dos métodos como los siguientes?

void metodo1(int j, int k);

int metodo1(int k, int j);

a) Verdadero b) Falso

10) Cuando un programa Java con una clase MiClase es ejecutado usando la

expresión, "java MiClase hola mundo," ¿Cuál de las siguientes es correcta? a) args[0] tiene "MiClase " b) args[0] tiene "hola" c) args[1] tiene "hola" d) Ninguna de las Anteriores

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 141

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Respuestas a Unidad 1: Examen de Autoevaluación 1) b 2) a 3) d 4) c 5) b y c 6) a 7) d 8) d 9) b

10) b

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 143

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 2: Laboratorio de Clases y Objetos

Objetivos del Aprendizaje Al final esta unidad, usted será capaz de:

• Crear clases y objetos. • Invocar métodos de una clase. • Sobrecargar métodos en una clase.

Core Java Guía del Estudiante

Unidad 2: Laboratorio de Clases y Objetos Libro 1: Core Java 144

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Ejercicios de Laboratorio 1) Escriba un programa en Java que tenga dos clases, Empleado y

CalcularSueldo. Empleado tiene los siguientes detalles acerca del empleado: nombre, código de empleado, horas trabajadas y pago por hora. CalcularSueldo crea instancias de la clase Empleado, obtiene los detalles del empleado para calcular los pagos y los imprime en la salida estándar. Use el constructor de la clase Empleado para asignar valores a las diferentes variables.

Sugerencias Útiles: • Escriba una clase llamada Empleado. • Declare variables para almacenar el nombre del empleado, código, horas

trabajadas y pago por hora. El constructor de Empleado toma las variables declaradas como parámetros y tiene el código para inicializar estas variables.

• Escriba una clase llamada CalcularSueldo.

• Cree una instancia de Empleado y valores de muestra de los detalles del empleado se pasan como parámetros al constructor.

El sueldo del empleado se calcula a partir de los detalles del empleado y se imprime en la salida estándar.

2) Escriba un programa en Java que tenga las clases Area y Usuario. La clase Area tiene métodos estáticos sobrecargados con el nombre area()que pueden ser usados para calcular el área de un circulo, triángulo, rectángulo y un cilindro. Usuario usa los métodos de Area para calcular el área de diferentes figuras geométricas y la imprime en la salida estándar.

Sugerencias Útiles: • Cree una clase llamada Area. • Escriba cuatro métodos sobrecargados llamados area que tomen diferentes

números y tipos de datos como parámetros. Estos métodos se usan para calcular el área de un círculo, triangulo, rectángulo y cilindro.

• Escriba una clase llamada Usuario que invoque las diferentes versiones de area() en la clase Area con valores de prueba como parámetros. El valor retornado se imprime en la salida estándar.

• Área del Círculo = 3.14 * radio * radio • Área del triangulo = 0.5 * base * altura • Área del rectángulo = largo * ancho • Área del cilindro = 3.14 * radio * radio * altura

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 145

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

3) Cree dos clases llamadas Instructor y Curso. Instructor tiene el nombre del instructor, número de ID del instructor y disciplina. Curso tiene número del curso y el nombre del curso. Escriba métodos que le permitan guardar y obtener los datos. Cree una clase llamada CursoInstructor que tenga dos miembros de datos, son estos, número de curso y número de ID del instructor. Escriba métodos para guardar y obtener los datos. Escriba el método main que cree objetos de las tres clases y establezca datos en todos estos objetos. El programa debe ser capaz de buscar e imprimir el nombre de un instructor que enseña un curso, dado el número de curso.

Sugerencias Útiles: • Escriba una clase llamada Instructor. • Declare variables para almacenar el nombre del instructor, ID y disciplina. • Escriba métodos para obtener los valores de estas variables y asignar valores a

estas variables. • Escriba una clase llamada Curso. • Declare variables para almacenar el número y nombre del curso. • Escriba métodos para obtener los valores de estas variables y asignar valores a

estas variables. • Escriba una clase llamada CursoInstructor • Declare variables para almacenar el número del curso y el ID del instructor. • Escriba métodos para obtener los valores de estas variables y asignar valores a

estas variables. • Cree instancias de las clases Instructor, Curso y CursoInstructor • Use el método setter para inicializar las variables de cada clase con valores de

prueba. • Considere un número de curso de prueba como entrada y use la clase

CursoInstructor para encontrar al instructor que enseña ese curso e imprimirlo en la salida estándar.

4) Cree una enumeración llamada Curso con los nombres de los cursos de su

preferencia. Cree una clase llamada Programa y defina un método estático que reciba un número variable de cursos e imprima un mensaje particular para cada uno.

Sugerencias Útiles: • Escriba una enumeración llamada Curso y definale los cursos de su

preferencia. • Cree una clase llamada Programa. • En la clase anterior, defina un método estático que reciba varios cursos usando

la notación ‘...’.

Core Java Guía del Estudiante

Unidad 2: Laboratorio de Clases y Objetos Libro 1: Core Java 146

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

• Escriba un for que recorra el conjunto de cursos.

• Dentro del cuerpo de la anterior estructura iterativa, cree un switch que muestre un mensaje en particular para cada curso definico en la enumeración Curso.

• Pruebe el funcionamiento del método pasandole varias enumeraciones de Curso.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 147

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 3: Herencia

Objetivos del Aprendizaje Al final de esta unidad, usted será capaz de:

• Entender los fundamentos de la herencia. • Explicar el uso de las palabras reservadas this y super. • Describir cómo crear una jerarquía de herencia. • Explicar cómo sobrescribir los métodos. • Explicar el uso de la palabra reservada final.

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 148

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

1. Introducción La herencia es uno de los fundamentos de la programación orientada a objetos. Permite crear una jerarquía entre un grupo de clases que tiene características similares. Se puede tener una clase que define los atributos y comportamiento comunes a un grupo específico de clases. Todas las clases que son parte de este grupo específico pueden heredar los atributos y el comportamiento de esta clase común.

Se va a entender que es la herencia tomando un ejemplo de la vida real. Asuma que quiere crear una clase llamada ArbolDePino, que tiene las mismas características que la clase Arbol, además de algunas características adicionales. Una forma de hacerlo es rescribiendo las variables miembro (atributos) y los métodos (comportamiento) que ya estaban disponibles en la clase Arbol, también en la clase ArbolDePino, y luego añadir las características especiales a la clase ArbolDePino.

Sin embargo, Java proporciona una forma elegante de hacer lo anterior, usando el concepto de herencia. De acuerdo con este concepto, la clase ArbolDePino puede ser una subclase de la clase Arbol. Así, la clase ArbolDePino obtiene implícitamente todas las variables y métodos que tengan acceso protected, public y package. Adicionalmente, ArbolDePino puede añadir sus propias características especiales además de las características de la clase Arbol. Dado que ArbolDePino hereda de la clase Arbol, puede ser llamado un ‘tipo de’ Arbol.

La clase que define los atributos y el comportamiento común se denomina superclase. Las clases que heredan atributos y comportamiento de la clase general (superclase) se denominan subclases. Una superclase es una clase que es heredada por otras clases.

A continuación se discute cómo declarar clases usando la herencia en Java.

2. Sintaxis para Declarar Clases Usando Herencia en Java La sintaxis general para declarar una clase que hereda de una superclase es la siguiente:

class NombreSubClase extends NombreSuperClase {

// cuerpo de la SubClase

}

Una clase no puede ser su propia superclase. Una clase puede tener cualquier número de subclases, pero sólo puede tener una única superclase. Cada subclase de una clase será una forma especializada de su superclase.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 149

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

En el ejemplo anterior, la clase Arbol se llama superclase de la clase ArbolDePino, y la clase ArbolDePino se llama una subclase de Arbol. Para especificar que la clase ArbolDePino hereda de Arbol, se debe usar la siguiente declaración de clase:

class ArbolDePino extends Arbol {…}

Se va a volver a revisar el ejemplo de la clase ArbolDePino, que hereda de la clase Arbol. El código en el Ejemplo 3.1 muestra la declaración de ambas clases.

Ejemplo 3.1

El ejemplo ilustra como se realiza la herencia en Java. La clase ArbolDePino hereda de la clase base Arbol.

El código Java comienza aquí...

1. /*Definicion de la clase Arbol comienza aqui*/

2. class Arbol {

3. private String nombre;

4. private int edad;

5. private boolean conFlores;

6.

7. public String getNombre() {

8. return nombre;

9. }

10. 11. public void setNombre(String nuevoNombre) { 12. nombre = nuevoNombre; 13. } 14. 15. public int getEdad() { 16. return edad; 17. } 18. 19. public void setEdad(int nuevaEdad) { 20. edad = nuevaEdad; 21. } 22. 23. public boolean isConFlores() { 24. return conFlores; 25. }

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 150

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

26. 27. public void setConFlores(boolean nuevoConFlores) { 28. conFlores = nuevoConFlores; 29. } 30. }/* Definicion de la clase Arbol termina aqui */ 31. 32. /* Definicion de la clase ArbolDePino comienza aqui */ 33. class ArbolDePino extends Arbol { 34. private boolean conifero; 35. 36. public ArbolDePino() { 37. setNombre("Pino"); 38. conifero = true; 39. } 40. 41. public boolean isConifero() { 42. return conifero; 43. } 44. }/* Definicion de la clase ArbolDePino termina aqui */ 45. 46. /* Definicion de la clase HerenciaEjemplo comienza aqui */ 47. public class HerenciaEjemplo { 48. public static void main(String[] args) { 49. String nombreSuper; 50. String nombreSub; 51. Arbol superClase = new Arbol(); 52. ArbolDePino subClase = new ArbolDePino(); 53. 54. superClase.setEdad(36); 55. subClase.setEdad(68); 56. nombreSuper = superClase.getNombre(); 57. nombreSub = subClase.getNombre(); 58. 59. System.out.println("Contenido de Super Clase:"); 60. System.out.println("Nombre Arbol: " + nombreSuper); 61. System.out.println("Edad Arbol: " + superClase.getEdad()); 62.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 151

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

63. System.out.println("\nContenido de Sub Clase:"); 64. System.out.println("Nombre Arbol: " + nombreSub); 65. System.out.println("Edad Arbol: " + subClase.getEdad()); 66. System.out.println("Conifero: " + subClase.isConifero()); 67. } 68. }/* Definicion de la clase HerenciaEjemplo termina aqui */

El código Java termina aquí

La salida del programa anterior es como sigue:

Contenido de Super Clase:

Nombre Arbol: null

Edad Arbol: 36

Contenido de Sub Clase:

Nombre Arbol: Pino

Edad Arbol: 68

Conifero: true

De la salida del programa anterior se puede ver que la subclase ArbolDePino obtiene implícitamente todos los miembros de su superclase Arbol. Por eso la subclase ArbolDePino también tiene las variables de instancia nombre, edad y conFlores de su superclase. Adicionalmente, ArbolDePino tiene su propia característica especial. El atributo conifero es una característica especial de la clase ArbolDePino.

También se puede ver que la clase Arbol es una clase autónoma completamente independiente. Por lo tanto, una superclase de una subclase puede ser usada por su cuenta.

Fin del Ejemplo 3.1

Se ha visto como se hereda de una clase en Java.

Una subclase, en su declaración, usa la palabra reservada extends, seguida por el nombre de la superclase para especificar su superclase.

Se puede construir la jerarquía de subclases de una superclase en particular. Esto se llama jerarquía de herencia. Considere la Figura 3.1, que muestra una jerarquía de herencia.

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 152

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 3.1: Jerarquía de Herencia

En esta figura, la clase Examen es la superclase de ExamenSimple, ExamenPractico y ExamenCertificacion. ExamenPracticoAleatorio es una subclase de ExamenPractico. Note que ExamenPractico es la superclase de ExamenPracticoAleatorio.

La jerarquía mostrada en la Figura 3.1 se puede implementar en Java usando la palabra reservada extends, y otros conceptos de herencia.

A continuación se examinan algunos de los principales conceptos de herencia en Java.

3. Conceptos Esenciales de Herencia La herencia en Java tiene los mismos conceptos que en C++. Sin embargo, en Java están más simplificados y existe menos ambigüedad que en C++.

El primer concepto que se va a entender es qué componentes de una clase son heredados.

3.1 ¿Qué es Heredado?

Las variables miembro, también conocidas como campos y los métodos de la clase base son heredados. Los constructores de la clase base no son heredados. La herencia no implica automáticamente visibilidad o accesibilidad a los miembros de la clase base en la clase que hereda. Los modificadores de acceso controlan la accesibilidad de los miembros. Así, un miembro de datos privado de la clase base a pesar de que es heredado por la subclase no es accesible en forma directa por la subclase. Sólo usando un método getter provisto en la clase base, se puede acceder a este miembro privado.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 153

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Se aprenderá ahora acerca de la clase Object.

3.2 La Clase Object

Todas las clases en Java heredan de la clase java.lang.Object por defecto. Así, cualquier clase creada por el programador es una subclase de la clase Object. Java provee ciertos métodos en la clase Object, que están disponibles para todas las clases. Hay varios métodos útiles definidos en java.lang.Object. Dos de ellos, ampliamente utilizados son: equals() y toString(). Dado que Object es la clase base de todas las clases Java, se estudiaran estos dos métodos.

3.2.1 El Método equals()

El método equals() se usa para comparar dos referencias a objetos en relación con los valores que mantienen los objetos. Este método devuelve true sólo si las dos referencias a objetos que son comparadas refieren al mismo objeto, de lo contrario devuelve false. Si las dos referencias a objetos comparadas usando el método equals() apuntan a objetos diferentes, que tienen el mismo valor, el método equals() retorna false.

Considere el Ejemplo 3.2, que compara dos referencias a objeto StringBuffer sb1 y sb2.

Ejemplo 3.2

El ejemplo muestra el uso del método equals().

El código Java comienza aquí…

1. /*Definicion de la clase CompararEjemplo comienza aqui*/

2. public class CompararEjemplo {

3. /* Metodo main comienza aqui */

4. public static void main(String[] args) {

5. StringBuffer sb1 = new StringBuffer("Palabra");

6. StringBuffer sb2 = sb1;

7.

8. boolean iguales = sb1.equals(sb2);

9. System.out.println(iguales);

10. 11. sb2 = new StringBuffer("Palabra"); 12. iguales = sb1.equals(sb2); 13. System.out.println(iguales); 14. }/* Metodo main termina aqui */ 15. }/* Definicion de la clase CompararEjemplo termina aqui */

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 154

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

El código Java termina aquí

Después de ejecutar la sentencia sb1.equals(sb2), iguales tendrá un valor true. El método equals compara las dos referencias a objeto, y retorna el valor como true. Después de ejecutar la sentencia sb2 = new StringBuffer("Palabra"), sb2 tiene una nueva referencia a objeto, de aquí que sb1.equals(sb2) retorne false.

Fin del Ejemplo 3.2

El método equals() realiza una comparación profunda, compara los valores almacenados por dos objetos. Otra forma de comparar objetos es usar el operador ==, que determina si dos referencias hacen referencia al mismo objeto o no.

Por ejemplo, considere el siguiente código:

StringBuffer sb1 = new StringBuffer("Palabra");

StringBuffer sb2 = new StringBuffer("Palabra");

boolean iguales = (sb1 == sb2);

En este caso, iguales tendrá el valor false, porque sb1 y sb2 refieren a dos objetos StringBuffer diferentes, creados usando dos operaciones new, aún cuando el valor almacenado es el mismo ("Palabra"). Si dos referencias apuntan a la misma instancia de objeto, el operador == retornará true. Considere el siguiente código:

String s1 = "Hola";

String s2 = "Hola";

boolean iguales = (s1 == s2);

En este caso iguales tendrá true ya que s1 y s2 refieren a la misma instancia de la cadena de caracteres "Hola" creada en el repositorio de constantes de string.

Se puede sobreescribir la implementación de equals que está en la clase java.lang.Object. Por defecto, chequeará la referencia a objeto de dos objetos. Sin embargo, puede ser sobreescrito para revisar los valores almacenados en los objetos, y no sólo la referencia. Por ejemplo, la clase String tiene una implementación sobrecargada de equals() para comparar el valor en estos objetos. Considere el Ejemplo 3.3, que muestra este concepto.

Ejemplo 3.3

Este ejemplo muestra como el método equals() se usa en la clase String.

El código Java comienza aquí...

1. /*Definicion de la clase StringEjemplo comienza aqui*/

2. public class StringEjemplo {

3. /* Metodo main comienza aqui */

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 155

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

4. public static void main(String[] args) {

5. String str1 = new String("Palabra");

6. String str2 = str1;

7.

8. boolean iguales = str1.equals(str2);

9. System.out.println(iguales);

10. 11. str2 = new String("Palabra"); 12. iguales = str1.equals(str2); 13. System.out.println(iguales); 14. }/* Metodo main termina aqui */ 15. }/* Definicion de la clase StringEjemplo termina aqui */

El código Java termina aquí

Después de ejecutar la segunda sentencia str1.equals(str2), iguales retorna true, después de ejecutar la sentencia str2 = new String("Palabra"), str2 tiene una nueva referencia a objeto. Aún en este caso, los valores son comparados. De ahí que, str1.equals(str2) devuelve true.

Fin del Ejemplo 3.3 3.2.2 El Método toString()

El método toString() se usa para obtener información textual acerca de un objeto. La implementación de toString() en la clase Object da el nombre de la clase seguido por el carácter @, que a su vez es seguido por la representación hexadecimal sin signo del código hash asociado con el objeto. Cuando se escriben las clases se puede sobrescribir este método para dar información textual acerca de la clase de la forma que se quiera.

Hasta ahora, se han visto los diferentes métodos dentro de la clase Object. Se considera a continuación el uso de las palabras reservadas this y super.

3.3 Palabras Reservadas super y this

En el ejemplo de las clases Arbol y ArbolDePino discutido anteriormente, ArbolDePino es una subclase de la clase Arbol. Este ejemplo no usa ningún constructor para inicializar sus variables miembro. Por lo tanto, las variables miembro no son inicializadas con ningún valor por defecto en el programa, ellas tienen los valores por defecto proporcionados por el sistema.

La palabra reservada super se usa para acceder a los miembros de la superclase desde la subclase, y la palabra reservada this se usa para acceder a los miembros del

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 156

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

objeto actual. Considere por un momento otro ejemplo, que se muestra en la Figura 3.2, para entender el uso de la palabra reservada super.

Figura 3.2: Uso de la Palabra Reservada super()

La clase ExamenCertificacion extiende de la clase Examen. El constructor de ExamenCertificacion inicializa variables de instancia como idVale y idEstudiante. La variable de instancia fecha está definida como un miembro privado en Examen. Ésta ha sido inicializada llamando al constructor de la superclase. Se hizo llamando a super(new Date()).

Ahora se rescriben las clases Arbol y ArbolDePino ya discutidas para incluir constructores en ellas. En este caso, la clase Arbol tendrá algunos valores por defecto establecidos para los objetos de tipo Arbol. La clase ArbolDePino puede reutilizar los valores por defecto establecidos en la clase Arbol, usando la palabra reservada super.

Por lo tanto, se puede utilizar la palabra reservada super para invocar al constructor de la superclase. ArbolDePino hereda las variables de instancia nombre y edad de Arbol. Desde el constructor de ArbolDePino se puede acceder a la variable de

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 157

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

instancia nombre declarada en Arbol usando la palabra reservada super, se puede también usar la palabra reservada super dentro del constructor para invocar a un método declarado en la superclase.

Similarmente, se puede acceder a la variable de instancia nombre heredada por ArbolDePino desde Arbol, usando la palabra reservada this en la superclase. En el programa en el Ejemplo 3.4, la variable nombre es pasada como parámetro a uno de los constructores de la clase Arbol. Dentro del constructor se puede acceder tanto a la variables nombre como al parámetro nombre. Para diferenciar entre la variable de instancia y el parámetro, se accede a la variable de instancia nombre usando la palabra reservada this (this.nombre). El parámetro nombre se accede sin usar la palabra reservada this, porque el parámetro no pertenece al objeto, sino que es una variable local del método. Si el nombre de una variable de instancia no es el mismo que el de un parámetro de un constructor, no hay necesidad de usar la palabra reservada this para acceder a las variables de instancia.

Ejemplo 3.4

Este ejemplo ilustra como trabajan las palabras reservadas super y this en la clase que hereda.

El código Java comienza aquí…

1. /*Definicion de la clase Arbol comienza aqui*/

2. class Arbol {

3. private String nombre;

4. private int edad;

5. private boolean conFlores;

6.

7. public Arbol(String nombre, int edad) {

8. this.nombre = nombre;

9. this.edad = edad;

10. } 11. 12. public Arbol() { 13. this.nombre = "Roble"; 14. this.edad = 100; 15. } 16. 17. public Arbol(Arbol arbol) { 18. this.nombre = arbol.nombre; 19. this.edad = arbol.edad;

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 158

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

20. } 21. 22. public String getNombre() { 23. return nombre; 24. } 25. 26. public void setNombre(String nombre) { 27. this.nombre = nombre; 28. } 29. 30. public int getEdad() { 31. return edad; 32. } 33. 34. public void setEdad(int edad) { 35. this.edad = edad; 36. } 37. 38. public boolean isConFlores() { 39. return conFlores; 40. } 41. 42. public void setConFlores(boolean conFlores) { 43. this.conFlores = conFlores; 44. } 45. }/* Definicion de la clase Arbol termina aqui */ 46. 47. /* Definicion de la clase ArbolDePino comienza aqui */ 48. class ArbolDePino extends Arbol { 49. private boolean conifero; 50. 51. public ArbolDePino() { 52. super(); 53. setNombre("Pino"); 54. conifero = true; 55. } 56.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 159

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

57. public ArbolDePino(int edad, boolean conico) { 58. super("Pino", edad); 59. conifero = conico; 60. } 61. 62. public ArbolDePino(ArbolDePino arbolDePino) { 63. super(arbolDePino); 64. conifero = arbolDePino.conifero; 65. } 66. 67. public boolean isConifero() { 68. return conifero; 69. } 70. }/* Definicion de la clase ArbolDePino termina aqui */ 71. 72. /* Definicion de la clase SuperEjemplo comienza aqui */ 73. public class SuperEjemplo { 74. public static void main(String[] args) { 75. Arbol arbol1 = new Arbol(); 76. System.out.println("Contenido de arbol1:"); 77. System.out.println("Nombre Arbol: " 78. + arbol1.getNombre()); 79. System.out.println("Edad Arbol: " 80. + arbol1.getEdad()); 81. 82. Arbol arbol2 = new Arbol("Mango", 64); 83. System.out.println("\nContenido de arbol2:"); 84. System.out.println("Nombre Arbol: " 85. + arbol2.getNombre()); 86. System.out.println("Edad Arbol: " 87. + arbol2.getEdad()); 88. 89. Arbol arbol3 = new Arbol(arbol2); 90. System.out.println("\nContenido de arbol3:"); 91. System.out.println("Nombre Arbol: " 92. + arbol3.getNombre()); 93. System.out.println("Edad Arbol: "

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 160

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

94. + arbol3.getEdad()); 95. 96. ArbolDePino pino1 = new ArbolDePino(); 97. System.out.println("\nContenido de pino1:"); 98. System.out.println("Nombre Arbol: " 99. + pino1.getNombre()); 100. System.out.println("Edad Arbol: "

101. + pino1.getEdad());

102. System.out.println("Conifero : "

103. + pino1.isConifero());

104.

105. ArbolDePino pino2 = new ArbolDePino(35, true);

106. System.out.println("\nContenido de pino2:");

107. System.out.println("Nombre Arbol: "

108. + pino2.getNombre());

109. System.out.println("Edad Arbol: "

110. + pino2.getEdad());

111. System.out.println("Conifero : "

112. + pino2.isConifero());

113.

114. ArbolDePino pino3 = new ArbolDePino(pino2);

115. System.out.println("\nContenido de pino3:");

116. System.out.println("Nombre Arbol: "

117. + pino3.getNombre());

118. System.out.println("Edad Arbol: "

119. + pino3.getEdad());

120. System.out.println("Conifero : "

121. + pino3.isConifero());

122. }

123. }/* Definicion de la clase SuperEjemplo termina aqui */

El código Java termina aquí

La salida de este programa es la siguiente:

Contenido de arbol1:

Nombre Arbol: Roble

Edad Arbol: 100

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 161

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Contenido de arbol2:

Nombre Arbol: Mango

Edad Arbol: 64

Contenido de arbol3:

Nombre Arbol: Mango

Edad Arbol: 64

Contenido de pino1:

Nombre Arbol: Pino

Edad Arbol: 100

Conifero : true

Contenido de pino2:

Nombre Arbol: Pino

Edad Arbol: 35

Conifero : true

Contenido de pino3:

Nombre Arbol: Pino

Edad Arbol: 35

Conifero : true

En este programa, la clase Arbol define tres constructores sobrecargados diferentes. ArbolDePino usa los tres constructores cuando define sus constructores usando super().

Fin del Ejemplo 3.4

Teniendo una idea general de la palabra reservada super, se verá en detalle su uso en la herencia.

3.3.1 Usar super en Clases Derivadas – Un Enfoque Detallado

En términos generales, una subclase se puede referir a su superclase inmediata usando la palabra reservada super. La palabra reservada super puede usarse en dos formas diferentes. La primera forma se usa cuando se invoca al constructor de la superclase, mientras que la segunda se usa para acceder a las variables miembro de la superclase que han sido ocultadas por las variables miembro de la subclase. En el programa del Ejemplo 3.4 se vio que el uso de la primera forma de la palabra clave super. El uso de la segunda forma de la palabra clave super será ilustrado posteriormente.

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 162

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Una subclase puede ocultar una variable de su superclase teniendo su propia variable con el mismo nombre que el de la superclase.

La forma general de la palabra reservada super usada por el constructor de la subclase para llamar al constructor de la superclase es como sigue:

super(listaDeParametros);

Cuando una subclase usa la palabra reservada super en la forma descrita, el compilador busca por la correspondencia exacta en la lista de parámetros de los diferentes constructores de la superclase. Si se encuentra una correspondencia, se usa ese constructor particular, como se ilustró en el programa del Ejemplo 3.4.

Véase el siguiente constructor definido por la clase ArbolDePino.

ArbolDePino(ArbolDePino ap) {

super(ap);

conifero = ap.conifero;

}

En este código, super() se usa con un objeto del tipo ArbolDePino y no del tipo Arbol. Pero aún así, se invoca al constructor de la forma Arbol(Arbol arbol), esto se debe a que una variable referenciando a un objeto de la superclase también puede usarse para referenciar al objeto de una clase que deriva de ella. Por lo tanto, se puede pasar el objeto ArbolDePino al constructor Arbol(Arbol arbol). En este caso, el objeto arbol puede acceder solamente a los miembros presentes en la clase Arbol. No conoce acerca de los miembros adicionales de la clase ArbolDePino. De esta forma, el miembro conifero se le asigna valor por separado en el constructor ArbolDePino() después de invocar al constructor de la clase Arbol mediante super(). Usualmente si se usa super(), entonces será la primera sentencia en el constructor de una subclase, de lo contrario el compilador generará un error. Aquí super() permite referir al constructor de la superclase inmediata (Arbol) de la clase actual (ArbolDePino).

La palabra reservada super también sirve para referir a las variables miembro o a los métodos miembro de la superclase. Este uso de la palabra reservada super es similar al uso de la palabra reservada this. La forma general del uso de super se da a continuación:

super.nombreDeMiembro

Aquí, nombreDeMiembro puede referir tanto a una variable como a un método de instancia de la superclase. Se verá en un ejemplo como acceder a un método de la superclase desde un método en la subclase en la sección Sobrescritura de Métodos.

La herencia tiene un comportamiento diferente cuando se usa junto a un modificador de acceso. A continuación se considera ese aspecto.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 163

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

3.3.2 Herencia y Modificadores de Acceso A continuación se va a entender si una subclase tiene acceso o no a todas las variables (atributos) y métodos (comportamiento) declarados en su superclase, o la superclase de su superclase, y así sucesivamente. Una subclase puede acceder a todas las variables y métodos declarados como public y protected de su superclase. Si la superclase está presente en el mismo paquete que la subclase, entonces la subclase puede acceder a todas las variables y métodos declarados como package en su superclase. Para más información sobre éstos modificadores de acceso refiérase a la Unidad 1 – Clases y Objetos de este volumen.

Las variables declaradas como private no pueden accederse desde la clase derivada.

En el Ejemplo 3.1, el atributo nombre de Arbol no es accesible por ArbolDePino, porque está declarado como private, pero dado que Arbol provee una forma de acceder al atributo nombre a través de los métodos getNombre() y setNombre(), ArbolDePino puede, indirectamente acceder al atributo, y asignarle el valor de "Arbol" dentro de su constructor.

En la Figura 3.3, el constructor de ArbolDePino accede a la variable private nombre de Tree, esto no está permitido. Una solución mejor será usar el método setNombre.

Figura 3.3: Herencia y Modificadores de Acceso

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 164

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

A continuación se discute acerca de herencia múltiple y jerarquía de herencia en Java.

3.3.3 Herencia Múltiple en Java Java no soporta directamente la herencia múltiple. Esto significa que una clase no puede tener más de una superclase directa. Sin embargo, Java indirectamente ayuda a implementar la herencia múltiple a través del uso de interfaces. Esto será tratado en detalle en la Unidad 5 – Clases Abstractas e Interfaces en este volumen.

3.4 Jerarquía de Herencia

Se aprendió acerca de jerarquía de herencia simple, que consiste de una superclase y una subclase. En esta sección, se verá como escribir programas Java que construyen una jerarquía de herencia multinivel, en la cual una clase que es una subclase de una clase, será una superclase de otra.

Se va a alterar el programa del ejemplo anterior para ilustrar una jerarquía de herencia multinivel. ArbolConifero será una subclase de Arbol, y ArbolDePino será una subclase de ArbolConifero .

Ejemplo 3.5

Este ejemplo muestra como crear una jerarquía de herencia multinivel usando tres clases. Este ejemplo da una completa descripción para las tres clases. Los métodos se proporcionan para destacar los puntos esenciales de la herencia multinivel.

El código Java comienza aquí...

1. /*Definicion de la clase Arbol comienza aqui*/

2. class Arbol {

3. protected String nombre;

4. protected int edad;

5.

6. public Arbol(String nombre, int edad) {

7. this.nombre = nombre;

8. this.edad = edad;

9. }

10. 11. public String getNombre() { 12. return nombre; 13. } 14. 15. public int getEdad() { 16. return edad; 17. }

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 165

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

18. }/* Definicion de la clase Arbol termina aqui */ 19. 20. /* Definicion de la clase ArbolConifero comienza aqui */ 21. class ArbolConifero extends Arbol { 22. private boolean conifero; 23. 24. public ArbolConifero(String nombre, int edad) { 25. super(nombre, edad); 26. conifero = true; 27. } 28. 29. public boolean isConifero() { 30. return conifero; 31. } 32. }/* Definicion de la clase ArbolConifero termina aqui */ 33. 34. /* Definicion de la clase ArbolDePino comienza aqui */ 35. class ArbolDePino extends ArbolConifero { 36. private String lugarDondeCrece; 37. 38. public ArbolDePino( 39. String nombre, 40. int edad, 41. String lugarDondeCrece) { 42. 43. super(nombre, edad); 44. this.lugarDondeCrece = lugarDondeCrece; 45. } 46. 47. public String getLugarDondeCrece() { 48. return lugarDondeCrece; 49. } 50. }/* Definicion de la clase ArbolDePino termina aqui */ 51. 52. /* Definicion de la clase comienza aqui */ 53. public class JerarquiaHerenciaEjemplo { 54. public static void main(String[] args) {

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 166

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

55. ArbolDePino pino = new ArbolDePino( 56. "Pino", 57. 23, 58. "Malaysia"); 59. System.out.println("Arbol: " + pino.getNombre()); 60. System.out.println("Edad: " + pino.getEdad()); 61. System.out.println("Conifero: " + pino.isConifero()); 62. System.out.println("Lugar donde crece: " 63. + pino.getLugarDondeCrece()); 64. } 65. }/* Definicion de la clase termina aqui */

El código Java termina aquí

La salida de este programa es la siguiente:

Arbol: Pino

Edad: 23

Conifero: true

Lugar donde crece: Malaysia

Del programa anterior se puede ver que la clase ArbolConifero hereda todas las características de la clase Arbol y añade aquellas características que le resultan especiales (boolean conifero). La clase ArbolDePino hereda las características de ambas clases Arbol y ArbolConifero y añade su variable miembro lugarDondeCrece. En el método main se crea un objeto ArbolDePino. El constructor de ArbolDePino invoca al constructor de su superclase usando super(nombre, edad). Se puede ver del programa anterior que super()se refiere a la superclase inmediata de la clase que invoca, también se puede ver que todos los parámetros del constructor de la superclase son pasados cuando se invoca, a pesar de que el constructor de la subclase puede no requerir todos estos parámetros. Estos parámetros son pasados hacia arriba, desde el nivel más bajo al más alto nivel en la jerarquía.

Fin del Ejemplo 3.5

Se discute a continuación el orden de construcción de los objetos.

3.4.1 Orden de Construcción de los Objetos En una jerarquía de herencia, es importante saber el orden de construcción de los objetos, cuando un objeto de una subclase se crea en la jerarquía. El constructor de la clase base (superclase) se llama primero, seguido por los constructores de las subclases, en el mismo orden en el cual las subclases fueron creadas.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 167

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Ejemplo 3.6

El ejemplo muestra como se construyen los objetos.

El código Java comienza aquí…

1. /*Definicion de la clase X comienza aqui*/

2. class X {

3. public X() {

4. System.out.println("Objeto de la clase X construido!");

5. }

6. }/* Definicion de la clase X termina aqui */

7.

8. /*Definicion de la clase Y comienza aqui*/

9. class Y extends X {

10. public Y() { 11. System.out.println("Objeto de la clase Y construido!"); 12. } 13. }/* Definicion de la clase Y termina aqui */ 14. 15. /*Definicion de la clase Z comienza aqui*/ 16. class Z extends Y { 17. public Z() { 18. System.out.println("Objeto de la clase Z construido!"); 19. } 20. }/* Definicion de la clase Z termina aqui */ 21. 22. /*Definicion de la clase comienza aqui*/ 23. public class OrdenConstruccionObjetosEjemplo { 24. public static void main(String[] args) { 25. new Z(); 26. } 27. }/* Definicion de la clase termina aqui */

El código Java termina aquí…

La salida del código anterior será la siguiente:

Objeto de la clase X construido!

Objeto de la clase Y construido!

Objeto de la clase Z construido!

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 168

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Fin del Ejemplo 3.6

El ejemplo anterior muestra que el objeto de la clase base X se construye primero, seguidos por los objetos de Y y Z.

El sobrescribir métodos es otro concepto importante en herencia.

3.5 Sobrescritura de Métodos

En una jerarquía de clases, donde una clase es una subclase de otra clase, si un método en la subclase tiene la misma firma (el mismo nombre de método, el mismo número de argumentos y los mismos tipos de argumentos en el mismo orden), que un método en la superclase, entonces el método en la superclase se dice que está sobrescrito (ocultado) por el método en la subclase. Cuando se invoca un método sobrescrito desde la subclase, siempre se refiere al método definido dentro de la subclase. La versión del método que se encuentra en la superclase que está sobrescrita (oculta) puede ser accedido usando la palabra clave super dentro de la subclase.

Ejemplo 3.7

Este ejemplo ilustra cómo se sobrescriben los métodos en las clases heredadas.

El código Java comienza aquí...

1. /*Definicion de la clase X comienza aqui*/

2. class X {

3. int a, b, c;

4.

5. X(int m, int n) {

6. a = m;

7. b = n;

8. }

9.

10. public int add() { 11. return (c = a + b); 12. } 13. }/* Definicion de la clase X termina aqui */ 14. 15. /* Definicion de la clase Y comienza aqui */ 16. class Y extends X { 17. int d; 18. 19. Y(int m, int n, int o) {

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 169

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

20. super(m, n); 21. d = o; 22. } 23. 24. /* Metodo sobrescrito */ 25. public int add() { 26. int s = super.add(); 27. return (c = s + d); 28. // return (c = super.add() + d); 29. } 30. }/* Definicion de la clase Y termina aqui */ 31. 32. /* Definicion de la clase comienza aqui */ 33. public class SobrescrituraMetodosEjemplo { 34. public static void main(String[] args) { 35. X x = new X(42,35); 36. Y y = new Y(42,35,23); 37. System.out.println( 38. "Suma en la super clase: " + 39. x.add()); 40. System.out.println( 41. "Suma en la sub-clase: " + 42. y.add()); 43. } 44. }/* Definicion de la clase termina aqui */

El código Java termina aquí

La salida del programa es la siguiente:

Suma en la super clase: 77

Suma en la sub-clase: 100

Del programa anterior, se puede ver que cuando se invoca el método add() en el objeto de la clase Y, se invoca al método add() definido en Y. El método add() definido en su superclase está sobrescrito u oculto. Cuando los métodos dentro de la clase Y quieren acceder al método sobrescrito de la clase X, pueden usar la palabra reservada super como se mostró en el programa anterior.

Fin del Ejemplo 3.7

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 170

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Si un método en la superclase y en la subclase tienen el mismo nombre, pero sus firmas son diferentes, entonces los métodos son sobrecargados y no sobrescritos. En este caso, el método en la superclase no está oculto y es accesible directamente, sin usar la palabra reservada super.

3.6 Comportamiento Virtual y Herencia

En Java todos los métodos son virtuales por defecto. Por virtual se entiende que todos los métodos en Java son polimórficos por naturaleza. El comportamiento asociado con los métodos polimórficos se denomina comportamiento virtual, ya que el comportamiento correcto es determinado en tiempo de ejecución. La Figura 3.4 muestra dos clases, Examen y ExamenPractico que tienen una relación de herencia (es decir, la clase ExamenPractico hereda de la clase Examen). Referencias al objeto ExamenPractico pueden ser asignadas a objetos del tipo Examen. Ahora, cuando se invoca a un método de este objeto Examen, se llama al método de la clase derivada (ExamenPractico). El enlace se realiza en tiempo de ejecución.

A una referencia a objeto de la superclase se le puede asignar una referencia a cualquier objeto de su subclase. Esto se usa ampliamente especialmente en el manejo de excepciones, que será discutido en el Volumen 3, Unidad 1 – Manejo de Excepciones y Tipos de Excepciones.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 171

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 3.4: Comportamiento Virtual en Java

El programa en el Ejemplo 3.8 se usa para ilustrar el comportamiento virtual discutido anteriormente, usando el ejemplo 3.1 de las clases Arbol y ArbolDePino.

Ejemplo 3.8

Este ejemplo muestra como usar comportamiento virtual en un programa Java.

El código Java comienza aquí...

1. /* Definicion de la clase comienza aqui */

2. public class ComportamientoVirtualEjemplo {

3. public static void main(String[] args) {

4. ArbolDePino ap = new ArbolDePino();

5. Arbol a = new Arbol();

6. ap.setEdad(75);

7.

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 172

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

8. System.out.println(

9. "Valores de la referencia de la sub clase: ");

10. System.out.println("Nombre: " + ap.getNombre()); 11. System.out.println("Edad: " + ap.getEdad()); 12. System.out.println("Conifero: " + ap.isConifero()); 13. 14. /* Asignando la referencia del objeto 15. ArbolDePino a la referencia del tipo Arbol */ 16. a = ap; 17. System.out.println( 18. "Valores de la referencia de la super clase: "); 19. System.out.println("Nombre: " + a.getNombre()); 20. System.out.println("Edad: " + a.getEdad()); 21. 22. // Esto generaria un error 23. // System.out.println("Conifero: " + a.isConifero()); 24. } 25. }/* Definicion de la clase termina aqui */

El código Java termina aquí

La salida del programa es la siguiente:

Valores de la referencia de la sub clase:

Nombre: Pino

Edad: 75

Conifero: true

Valores de la referencia de la super clase:

Nombre: Pino

Edad: 75

En este programa, ap es una referencia al objeto ArbolDePino, y a es una referencia al objeto Arbol. En la primera parte del programa, se usa directamente ap para acceder a sus métodos. En la segunda parte del programa, se le asigna ap a a en la línea 16 como sigue:

a = ap;

ArbolDePino es una subclase de Arbol y por eso se le puede asignar ap a a. Esto implica que la referencia a un objeto de la superclase se le puede asignar la referencia de su subclase. Cuando se accede a los métodos de ArbolDePino usando a, no se puede acceder a isConifero(), porque no está presente en la superclase Arbol.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 173

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Todos los métodos definidos en la clase base son accesibles a través de a. Por lo tanto, cuando se asigna la referencia a la subclase a una referencia de superclase, solamente aquellos métodos que están disponibles en la superclase pueden ser accedidos usando la referencia.

Fin del Ejemplo 3.8

El punto a destacar aquí es que la referencia al objeto de superclase que actualmente referencia a su subclase permite acceder solamente a aquellas variables de la subclase que han sido heredadas de la superclase. Por esto la referencia a no puede acceder al miembro conifero, que está presente solamente en ArbolDePino, y no en Arbol. Esto es así, porque la superclase no conoce de las características especiales añadidas por la subclase. Esta es la razón por la que la línea 23 de la función main, a.isConifero() está comentada.

La asignación a = new ArbolDePino() es conocida como upcast y es legal en Java. Sin embargo, no se puede tener ap = new Arbol(), que es referido como downcast. Si se desea asignar a a ap después de hacer a = new ArbolDePino(), se debe realizar una conversión explícita como se muestra a continuación:

ap = (ArbolDePino) a;

A continuación se aprenderá acerca del uso de la palabra reservada final en el contexto de herencia.

3.7 Herencia y la Palabra Reservada final

Se puede declarar una variable que tenga un valor constante a través del programa usando el modificador final sobre la variable. Una variable final puede ser inicializada solamente una vez dentro de un programa Java, y mantendrá el mismo valor a través de todo el programa. No se puede cambiar el valor asignado a una variable final más adelante en el programa.

Ejemplo 3.9

Este ejemplo ilustra como la palabra clave final se puede usar en las clases.

El código Java comienza aquí…

1. /* Definicion de la clase comienza aqui */

2. public class VariableFinalEjemplo {

3. /* El metodo main comienza aqui */

4. public static void main(String[] args) {

5. final int contador = 10;

6. int a = 10;

7. System.out.println(

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 174

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

8. "Valor de la variable contador es: " +

9. contador);

10. a = a + contador; 11. System.out.println( 12. "Valor de la variable a es: " + 13. a); 14. contador++; // Error de compilacion 15. contador = 25; // Error de compilacion 16. }/* El metodo main termina aqui */ 17. }/* Definicion de la clase termina aqui */

El código Java termina aquí

En este programa se puede inicializar la variable final contador sólo una vez y usarla subsecuentemente dentro del programa sin alterar su valor. Cuando se intenta actualizar contador o asignarle un nuevo valor, se lanza un error de compilación como ocurre en las líneas 14 y 15.

Fin del Ejemplo 3.9

El Ejemplo 3.9 muestra el uso de la palabra clave final para declarar constantes. El uso de final con las clases derivadas tiene un impacto diferente, que se verá a continuación. Uso de la Palabra Reservada final para prevenir la Herencia

Cuando se quiere evitar que una clase se herede, se puede usar el modificador final en la declaración de la clase. Cuando se declara una clase como final, Java declara implícitamente todos los métodos de la clase también como final. No se puede declarar una clase abstract como final, dado que la clase abstracta requiere que sus subclases proporcionen las implementaciones completas para todos sus métodos. Este concepto será estudiado en detalle en la Unidad 5 – Clases Abstractas e Interfaces de este volumen.

Ejemplo 3.10

El programa ilustra el uso del modificador final para una clase.

El código Java comienza aquí…

1. final class X {

2. private int a;

3. X(int m) {

4. a = m;

5. }

6. public void setA(int m) {

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 175

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

7. a = m;

8. }

9. public int getA() {

10. return (a); 11. } 12. } 13. 14. /* error de compilación, Y no puede ser subclase de X */ 15. class Y extends X { 16. public int b; 17. Y(int m, int n) { 18. super(m); 19. b = n; 20. } 21. }

El código Java termina aquí

Como se discutió, la clase Y no puede heredar de la clase X, porque X fue declarada como final.

Fin del Ejemplo 3.10

A continuación se discute el uso de la palabra reservada final para evitar la sobrescritura de métodos de una superclase por su subclase.

3.7.1 Uso de la Palabra Reservada final Para Prevenir la Sobrescritura

En esta sección veremos el uso de la palabra reservada final en la declaración de los métodos para evitar que el método sea sobrescrito.

A pesar de que sobrescribir métodos es sin duda, una característica importante en Java, puede haber situaciones donde no se quiere que un método sea sobrescrito por sus subclases para mejorar el desempeño del programa. Esto se debe a que, en este caso, el compilador sabe que estos métodos final no serán sobrescritos por sus subclases, y directamente remplaza el código fuente por el bytecode, mejorando el rendimiento del programa. Esto se llama enlace temprano (early binding). Generalmente el compilador Java resuelve la invocación de métodos en tiempo de ejecución, esto se llama enlace tardío (late binding). Se puede usar el modificador final al declarar métodos para conseguir el enlace temprano.

Considere el Ejemplo 3.11. Se modificará el programa del Ejemplo 3.10, para ilustrar el uso de final en la declaración de métodos para prevenir el sobrescribir.

Ejemplo 3.11

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 176

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

El código Java comienza aquí...

1. class X {

2. int a, b, c;

3.

4. X(int m, int n) {

5. a = m;

6. b = n;

7. }

8.

9. final int add() {

10. c = a + b; 11. return (c); 12. } 13. } 14. 15. class Y extends X { 16. int d; 17. 18. Y(int m, int n, int o) { 19. super(m, n); 20. d = o; 21. } 22. 23. /* Error de compilacion: Metodo 24. final no puede ser sobrescrito */ 25. public int add() { 26. int s = super.add(); 27. c = s + d; 28. return (c); 29. } 30. }

El código Java termina aquí

En este ejemplo, dado que el método add() ha sido declarado como final en la clase X, no puede ser sobrescrito en la clase Y, que se extiende de la clase X. Por lo tanto, se obtiene un error de compilación.

Fin del Ejemplo 3.11

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 177

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Resumen Ahora que ha completado esta unidad, usted debe ser capaz de:

• Explicar los fundamentos de la herencia. • Explicar el uso de las palabras reservadas super y this. • Describir cómo crear una jerarquía de herencia. • Discutir cómo sobrescribir métodos. • Explicar el uso de la palabra reservada final.

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 178

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 3: Examen de Autoevaluación 1) ¿Cuál modificador debe usarse para modificar una variable para hacerla

inaccesible por la subclase? a) protected b) public c) package d) private

2) Una clase que es subclase de una clase puede ser una superclase de alguna otra

clase. a) Verdadero b) Falso

3) Por defecto, ¿desde cuál de las siguientes heredan todas las clases en Java?

a) Clase Base b) Clase Super c) Clase Object d) Ninguna de las anteriores

4) Una clase puede tener cualquier número de superclases directas y subclases.

a) Verdadero b) Falso

5) Si X es la superclase de Y, ¿cuál de las siguientes es un uso correcto?

a) X x = new X(); Y y = new Y(); x = y; b) X x = new X(); Y y = new Y(); y = x;

6) Cuando a una variable de referencia de una superclase se le asigna una referencia

a una subclase, el acceso está disponible sólo para los miembros que se definen en la superclase. a) Verdadero b) Falso

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 179

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

7) Cuando se usa el objeto de una subclase Y que deriva de una clase X, en una clase externa Z, se puede hacer referencia a los métodos de la clase X usando la palabra clave super con el objeto de la clase Y. a) Verdadero b) Falso

8) A es la superclase de B, y B es la superclase de C. Cuando un objeto de C es

creado, ¿cuál es el orden en el que los constructores se invocan? a) Sólo el constructor de C es invocado b) Constructor de C, Constructor de B, Constructor de A c) Constructor de A, Constructor de B, Constructor de C d) Constructor de A, Constructor de C

9) ¿Cuál es la palabra clave usada en Java para detener la sobrescritura de métodos

en subclases? a) static b) stop c) final d) private

10) Cuando se usa la palabra clave final con una variable, ésta no puede ser

ocultada por una subclase con una variable con el mismo nombre. a) Verdadero b) Falso

Core Java Guía del Estudiante

Unidad 3: Herencia Libro 1: Core Java 180

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Respuestas a la Unidad 3: Examen de Autoevaluación 1) d 2) a 3) c 4) b 5) a 6) a 7) b 8) c 9) c

10) b

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 181

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 4: Laboratorio de Herencia

Objetivos de Aprendizaje Al final de esta unidad, usted será capaz de:

• Trabajar con herencia. • Invocar métodos de una superclase.

Core Java Guía del Estudiante

Unidad 4: Laboratorio de Herencia Libro 1: Core Java 182

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Ejercicios de Laboratorio 1) Escribir un programa en Java, que tenga una clase llamada Color. La clase

Color tiene un atributo colorNombre que es privado y los siguientes métodos, final void setColor(String color);

String getColor(); // la cadena retornada da el color

La clase Blanco hereda de la clase Color y tiene su atributo (private) colorNombre establecido en “Blanco”.

Las clases Violeta, Índigo, Azul, Verde, Amarillo, Naranja y Rojo heredan de la clase Blanco. Todas estas clases tienen una variable privada llamada colorNombre que es inicializada con "violeta", "índigo", "azul", “verde”, "amarillo", "naranja" y "rojo", respectivamente.

La clase Prisma tiene el siguiente método,

void activatePrisma(Color c);

Este método verifica si el método getColor() retorna "blanco". Si es verdadero, crea instancias de las clases Violeta, Índigo, Azul, Verde, Amarillo, Naranja y Rojo e imprime en la salida estándar sus atributos colorNombre. Si la verificación resulta en falso.

La clase AntiPrisma tiene el siguiente método,

void activateAntiPrisma(Rojo r, Azul a, Verde v);

Este método verifica si el atributo colorName de r, a y v son "rojo", "azul" y "verde", respectivamente. Si es verdadero, crea un nuevo objeto Blanco e imprime el valor de su atributo colorNombre en la salida estándar.

La clase Cientifico usa las clases Prisma y AntiPrisma.

2) Escribir un programa en Java que tenga una clase llamada Bicicleta con ruedas, asiento, velocímetro, indicador, frenoDelantero, frenoTrasero y velocidadCajaActual como atributos. También tiene un método llamado incrementaVelocidadCaja que realiza los cambios desde 1 hasta 4 y un método llamado decrementaVelocidadCaja que realiza los cambios desde 4 hasta 1. La clase Bicicleta también tiene un método llamado indicaGiro() que cambia el valor de la variable indicador en forma concordante. Una clase llamada BicicletaCarrera es subclase de la clase Bicicleta y sobrescribe el método incrementaVelocidadCaja para hacer los cambios desde 1 hasta 5, y el método decrementaVelocidadCaja se sobrescribe para hacer los cambios desde 5 hasta 1. Un Conductor (otra clase) maneja la Bicicleta y la BicicletaCarrera, una después de la otra.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 183

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 5: Clases Abstractas e Interfaces

Objetivos de Aprendizaje Al final de esta unidad, usted será capaz de:

• Explicar clases abstractas. • Diferenciar entre clases abstractas y clases concretas. • Describir cómo definir clases y métodos abstractos en Java. • Definir una interfaz. • Explicar cómo las interfaces son implementadas y usadas como referencia.

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 184

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

1. Introducción Se estudió la herencia en Java en la Unidad 3 - Herencia. En esta unidad, se tratará el tema de clases abstractas e interfaces, las cuales pueden usarse por la herencia.

2. Clases Abstractas En todas las unidades anteriores, hasta la Unidad 3 – Herencia, se han discutido solamente las clases concretas. Estas clases se denominan así porque se pueden instanciar objetos de ellas. Existe otro grupo de clases que no pueden instanciarse, se denominan clases abstractas. Por lo tanto, el operador new no puede usarse en las clases abstractas.

Las clases abstractas se usan para definir las características generales de un concepto abstracto. Una clase abstracta se usa para definir los atributos comunes y el comportamiento general de un grupo de clases. Las clases abstractas tienen las definiciones de métodos que justifican su comportamiento. Una clase abstracta puede implementar algunos de los métodos definidos en ella, obteniéndose una implementación parcial de su comportamiento. Usualmente, no se implementa una gran parte de la clase (no se da la implementación de los métodos), algunas veces, sin embargo, las clases abstractas pueden implementar todos los métodos definidos en ella.

Las clases que heredan de una clase abstracta implementan los métodos abstractos definidos en esa clase. En caso de que la subclase no proporcione la implementación para todos los métodos abstractos definidos en la clase abstracta, la subclase misma se declara como una clase abstracta y la clase que herede de esta subclase abstracta debe proporcionar la implementación para sus métodos abstractos. De lo contrario la cadena de clases abstractas continúa.

Se va a entender el concepto de clases abstractas con dos ejemplos generales.

Considere tres especies de mamíferos: jirafas, delfines y ballenas, se pueden modelar estas especies como clases de software: Jirafa, Delfin y Ballena. Se conoce el aspecto de estos tres animales, y podemos visualizar cada uno de ellos.

Las jirafas, los delfines y las ballenas pertenecen a la categoría llamada mamíferos. Se pueden representar las características de los mamíferos en la forma de una clase llamada Mamifero. ¿Cuándo se piensa en un mamífero se puede visualizar cómo luce?, No, esto se debe a que un mamífero puede tener el aspecto de una jirafa, un delfín o una ballena, en nuestro ejemplo. Una clase abstracta puede ser usada para representar entidades que no pueden ser visualizadas. Mamifero puede ser una clase abstracta, no se pueden crear instancias de Mamifero. Sin embargo, se pueden crear instancias de sus subclases, llamadas, Jirafa, Delfin y Ballena.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 185

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Una de las características comunes a los mamíferos es que ellos dan a luz a sus pequeños. Sin embargo, las jirafas, delfines y ballenas dan a luz a sus pequeños en ambientes diferentes. Mientras la jirafa da a luz a su pequeño en tierra, un delfín y una ballena dan a luz en el agua. Por lo tanto, la clase Mamifero se puede usar solo para definir las características que ellos dan a luz a sus pequeños. No se puede usar para definir donde ellos dan a luz a sus pequeños.

De la discusión anterior está claro que existen algunos patrones genéricos de comportamiento de entidades del mundo real que pueden ser abstraídos en una sola clase, la cual forma la clase base para la herencia. En el ejemplo anterior, Mamifero es la clase abstracta, que forma la clase base, cuyos atributos y métodos podrán ser heredados por otras clases.

Considere otro ejemplo. El concepto de número es un concepto abstracto porque no existe un objeto llamado número en la realidad, lo que se tiene en el mundo real son enteros, números reales, etc., que comparten características o propiedades comunes. Estas características pueden ser abstraídas en una clase llamada Numero, que forma la clase base para las subclases Entero, Real, etc. La clase Numero se define como clase abstracta, ya que existe también sólo en abstracción en el mundo real.

Los dos ejemplos que se han discutido muestran como las clases abstractas son útiles para definir conceptos abstractos en Java. Otras clases concretas heredan de clases abstractas para concretizar su definición abstracta. Antes de avanzar más en lo concerniente a clases abstractas, se van a resumir las diferencias entre clases abstractas y concretas.

2.1 Clases Abstractas vs. Clases Concretas

La Tabla 5.1 ilustra las diferencias entre clases abstractas y concretas.

Clases Abstractas Clases Concretas

Se usan para generalizar clases concretas.

Se usan para representar objetos del mundo real.

No pueden ser instanciadas. Pueden ser instanciadas.

Definen métodos abstractos para los cuales la implementación no es provista.

No definen métodos abstractos.

Pueden o no proveer implementación para cualquiera de los métodos.

Deben proveer implementación para todos sus métodos.

Tabla 5.1: Clases Abstractas vs. Clases Concretas

Se va a mencionar a continuación como Java provee mecanismos para definir y usar clases abstractas en programas.

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 186

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

3. Uso de Clases Abstractas El modificador abstract que se aprendió en la Unidad 1 – Clases y Objetos, se puede usar de dos formas, ya sea con una clase o con un método. Cuando una clase tiene el modificador abstract en la declaración de la clase, se denomina clase abstracta. El modificador abstract se usa con una clase para indicar que la clase no puede ser instanciada.

La palabra clave abstract se usa antes de la palabra clave class para definir una clase como clase abstracta. El siguiente código muestra como declarar una clase abstract:

abstract class ClaseAbstracta{

// . . .

}

class InstanciacionClaseAbstractaEjemplo{

public static void main(String args[]){

ClaseAbstracta ca = new ClaseAbstracta(); // error

}

}

Cuando se intenta instanciar una clase abstract, como se hizo en la clase InstanciacionClaseAbstractaEjemplo, el compilador mostrará el siguiente mensaje de error:

InstanciacionClaseAbstractaEjemplo.java:6: ClaseAbstracta is abstract; cannot be instantiated

ClaseAbstracta ca = new ClaseAbstracta(); // error

^

1 error

Las clases abstractas pueden tener dos tipos de métodos: métodos que tienen implementación y métodos que no tiene implementación. Los métodos implementados en una clase abstracta son métodos concretos. Los métodos que no tienen implementación son métodos abstractos. Se van a definir los métodos abstractos en Java.

3.1 Definición de Métodos Abstractos

El modificador abstract, cuando se usa en una declaración de método, proporciona un método abstract. El modificador indica que la implementación del método no es provista en la clase. Indica que las subclases que hereden de la clase abstracta, al cual el método abstracto pertenece, deben proveer la implementación para el método. Si la subclase inmediata no provee implementación para el método abstracto de su superclase, entonces la subclase también se debe definir como una clase abstracta.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 187

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Los métodos abstractos pueden estar presentes solamente dentro de una clase abstracta. La siguiente es la estructura general de la declaración de un método abstracto:

abstract tipoRetorno nombreMetodo(argumentos);

La palabra reservada abstract se usa antes de especificar el tipo de retorno del método. Se puede ver que el cuerpo del método está ausente, lo que significa que la implementación del método no se proporciona en la clase.

Una clase abstracta puede contener cualquier número de métodos abstractos. Como se mencionó anteriormente, también es posible tener una clase abstracta que de la implementación para todos los métodos definidas en ella y así no tenga ningún método abstracto. Cuando una clase es declarada como abstracta, no necesariamente debe contener un método abstracto. Sin embargo cuando existe un método abstracto dentro de la clase, la clase debe ser declarada como abstracta. Antes de avanzar con ejemplos de clases y métodos abstractos, se va a ver como una referencia se puede usar para una clase abstracta.

3.2 Clases Abstractas y Referencias

Aunque no se puede instanciar una clase abstracta, se puede crear una referencia a ésta. Esto es posible porque Java soporta polimorfismo, que permite que un objeto de una clase sea referenciado por una referencia a su superclase. Considere el siguiente fragmento de código:

abstract class Abstracta {

abstract void m1();

}

class Concreta extends Abstracta {

void m1() {

System.out.println("En m1");

}

void m2() {

System.out.println("En m2");

}

}

public class AbstractaEjemplo {

public static void main(String args[]) {

Concreta c = new Concreta();

/* Referencia a la clase Abstracta */

Abstracta referenciaAbstracta;

referenciaAbstracta = c;

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 188

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

referenciaAbstracta.m1();

}

}

En el código anterior, se crea una referencia referenciaAbstracta de la clase Abstracta, a esta referencia se le pueden asignar referencias de subclases de Abstracta. Esta característica es muy útil para lograr el polimorfismo. Usando referenciaAbstracta en el código anterior, se puede hacer referencia al método m1() definido en la clase abstracta.

Una vez aprendido como definir clases y métodos abstractos, se va a considerar dos clases llamadas CuentaDeAhorros y CuentaCorriente. La representación gráfica de la clase CuentaDeAhorros y el código Java que la implementa se muestra en la Figura 5.2.

public class CuentaDeAhorros {private String numero;private double saldo;private double tasaInteres;

public void cerrar() {…}public double calcularIntereses() {…}public void credito(double cantidad){…}public void debito(double cantidad){…}public double getSaldo() {…}

}

CuentaDeAhorrosnumero:Stringsaldo:doubletasaInteres:double

cerrar():voidcalcularIntereses():doublecredito(double):voiddebito(double):voidgetSaldo():double

public class CuentaDeAhorros {private String numero;private double saldo;private double tasaInteres;

public void cerrar() {…}public double calcularIntereses() {…}public void credito(double cantidad){…}public void debito(double cantidad){…}public double getSaldo() {…}

}

public class CuentaDeAhorros {private String numero;private double saldo;private double tasaInteres;

public void cerrar() {…}public double calcularIntereses() {…}public void credito(double cantidad){…}public void debito(double cantidad){…}public double getSaldo() {…}

}

CuentaDeAhorrosnumero:Stringsaldo:doubletasaInteres:double

cerrar():voidcalcularIntereses():doublecredito(double):voiddebito(double):voidgetSaldo():double

CuentaDeAhorrosnumero:Stringsaldo:doubletasaInteres:double

cerrar():voidcalcularIntereses():doublecredito(double):voiddebito(double):voidgetSaldo():double

Figura 5.2: Representación de la Clase CuentaDeAhorros

En el diagrama de la clase CuentaCorriente y el código Java que la implementa se muestran en la Figura 5.3.

CuentaCorrientenumero:Stringsaldo:doublecomisionMensual:double

cargarComision():doublecerrar():voidcredito(double):voiddebito(double):voidgetSaldo():double

public class CuentaCorriente {private String numero;private double saldo;private double comisionMensual

public double cargarComision() {…}public void cerrar() {…}public void credito(double cantidad){…}public void debito(double cantidad){…}public double getSaldo() {…}

}

CuentaCorrientenumero:Stringsaldo:doublecomisionMensual:double

cargarComision():doublecerrar():voidcredito(double):voiddebito(double):voidgetSaldo():double

CuentaCorrientenumero:Stringsaldo:doublecomisionMensual:double

cargarComision():doublecerrar():voidcredito(double):voiddebito(double):voidgetSaldo():double

public class CuentaCorriente {private String numero;private double saldo;private double comisionMensual

public double cargarComision() {…}public void cerrar() {…}public void credito(double cantidad){…}public void debito(double cantidad){…}public double getSaldo() {…}

}

public class CuentaCorriente {private String numero;private double saldo;private double comisionMensual

public double cargarComision() {…}public void cerrar() {…}public void credito(double cantidad){…}public void debito(double cantidad){…}public double getSaldo() {…}

}

Figura 5.3: Representación de la Clase CuentaCorriente

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 189

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

De las Figuras 5.2 y 5.3, se pueden hacer las siguientes observaciones:

• Ambas clases tienen algunas funcionalidades en común. • Es posible crear instancias para ambas clases. • Las similitudes entre estas clases permite definir una jerarquía de herencia. • La forma de implementar las funcionalidades, es sin embargo drásticamente

diferente para ambas clases.

Para estas clases, se puede crear una clase en común llamada CuentaBancaria, que tenga funciones definidas en ella, sin la implementación, esta clase se convierte en candidata para una clase abstracta.

El diagrama de la clase CuentaBancaria se muestra en la Figura 5.4. Las definiciones abstractas están en letra itálica.

Figura 5.4: Clase Abstracta CuentaBancaria

La definición en Java de la clase CuentaBancaria se muestra en la Figura 5.5.

public abstract class CuentaBancaria {private String numero;private double saldo;

public abstract void cerrar();public void credito(double cantidad) {…}public abstract void debito(double cantidad);public double getSaldo() {…}

}

public abstract class CuentaBancaria {private String numero;private double saldo;

public abstract void cerrar();public void credito(double cantidad) {…}public abstract void debito(double cantidad);public double getSaldo() {…}

}

Figura 5.5: Definición en Java de la Clase CuentaBancaria

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 190

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Las dos clases, CuentaCorriente y CuentaDeAhorros, pueden ahora ser derivadas de la clase abstracta CuentaBancaria.

Figura 5.6: Derivando de la Clase Abstracta CuentaBancaria

Las dos clases: CuentaDeAhorros y CuentaCorriente extienden de la clase abstracta y proveen la implementación para los métodos definidos como abstractos. El código fuente para la clase CuentaCorriente se muestra en la Figura 5.7. Las implementaciones de los métodos se muestran en puntos suspensivos.

Figura 5.7: Definición en Java de la Clase CuentaCorriente

Se van a escribir dos programas Java que usan clases y métodos abstractos.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 191

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Ejemplo 5.1

Este ejemplo muestra como un método abstracto se implementa en la subclase V.

El código Java comienza aquí…

1. /* Definicion de la clase U comienza aqui */

2. abstract class U {

3. abstract void metodo1();

4. void metodo2() {

5. System.out.println(

6. "Dentro de metodo2 en la clase U");

7. }

8. }/* Definicion de la clase U termina aqui */

9.

10. /* Definicion de la clase V comienza aqui */ 11. class V extends U { 12. void metodo1() { 13. System.out.println( 14. "Dentro de metodo1 en la clase V"); 15. } 16. }/* Definicion de la clase V termina aqui */ 17. 18. /* Definicion de la clase AbstractaEjemplo comienza aqui */ 19. public class AbstractaEjemplo { 20. /* El metodo main comienza aqui */ 21. public static void main(String[] args) { 22. V subClase = new V(); 23. subClase.metodo1(); 24. subClase.metodo2(); 25. }/* El metodo main termina aqui */ 26. }/* Definicion de la clase AbstractaEjemplo termina aqui */

El código Java termina aquí

La salida del programa anterior es la siguiente:

Dentro de metodo1 en la clase V

Dentro de metodo2 en la clase U

De la salida del programa anterior, se puede ver que a pesar de que no se creó un objeto de la clase U, la clase V implícitamente tiene la implementación para el metodo2.

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 192

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Más aún, no puede crearse un objeto de la clase U, pues es una clase abstracta. También se puede notar que la clase abstracta proporciona la implementación para el método metodo2, lo cual es perfectamente aceptable.

Fin del Ejemplo 5.1

El próximo ejemplo ilustra como usar una referencia a una clase abstracta.

Ejemplo 5.2

Usando la clase abstracta Poligono, se crean tres subclases, se instancian tres objetos de estas tres clases y usando la referencia a la clase abstracta se invoca a los métodos en las subclases.

El código Java comienza aquí…

1. /* Definicion de la clase Poligono comienza aqui */

2. abstract class Poligono {

3. float dimension1;

4. float dimension2;

5.

6. Poligono(float x, float y) {

7. dimension1 = x;

8. dimension2 = y;

9. }

10. 11. abstract float area(); 12. }/* Definicion de la clase Poligono termina aqui */ 13. 14. /* Definicion de la clase Cuadrado comienza aqui */ 15. class Cuadrado extends Poligono { 16. Cuadrado(float side) { 17. super(side, side); 18. } 19. 20. float area() { 21. return (dimension1 * dimension2); 22. } 23. }/* Definicion de la clase Cuadrado termina aqui */ 24. 25. /* Definicion de la clase Triangulo comienza aqui */

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 193

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

26. class Triangulo extends Poligono { 27. Triangulo(float base, float altura) { 28. super(base, altura); 29. } 30. 31. float area() { 32. return ((float) 0.5 * dimension1 * dimension2); 33. } 34. }/* Definicion de la clase Triangulo termina aqui */ 35. 36. /* Definicion de la clase Cilindro comienza aqui */ 37. class Cilindro extends Poligono { 38. Cilindro(float radio, float altura) { 39. super(radio, altura); 40. } 41. 42. float area() { 43. return ((float) 3.14 * dimension1 * 44. dimension1 * dimension2); 45. } 46. }/* Definicion de la clase Cilindro termina aqui */ 47. 48. /* Definicion de la clase AbstractaEjemplo comienza aqui */ 49. public class AbstractaEjemplo { 50. /* El metodo main comienza aqui */ 51. public static void main(String[] args) { 52. Cuadrado cu = new Cuadrado(7); 53. Triangulo t = new Triangulo(4, 5); 54. Cilindro ci = new Cilindro(6, 3); 55. Poligono poligono; 56. 57. poligono = cu; 58. System.out.println( 59. "Area del cuadrado es: " + 60. poligono.area()); 61. 62. poligono = t;

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 194

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

63. System.out.println( 64. "Area del triangulo es: " + 65. poligono.area()); 66. 67. poligono = ci; 68. System.out.println( 69. "Area del cilindro es: " + 70. poligono.area()); 71. }/* El metodo main termina aqui */ 72. }/* Definicion de la clase AbstractaEjemplo termina aqui */

El código Java termina aquí

La salida del programa anterior sería así:

Area del cuadrado es: 49.0

Area del triangulo es: 10.0

Area del cilindro es: 339.12

En el programa anterior se puede ver que las características de la clase abstracta Poligono son más significativas con la implementación que proporcionan sus subclases para el método abstracto area(). No se puede tener una implementación significativa del método area() en un polígono de dos dimensiones. Por lo tanto, el método area() se declara como abstracto y su implementación se deja para sus subclases. Declarar el método area() como abstracto obliga a que todas sus subclases no abstractas implementen el método.

Fin del Ejemplo 5.2

En el programa anterior, se crea una referencia a la clase abstracta Poligono, pero no se crea un objeto del tipo Poligono.

La variable poligono del programa anterior, es sólo una referencia a la clase abstracta Poligono, esta variable permite referenciar objetos de sus subclases. Los métodos sobrescritos se resuelven en tiempo de ejecución usando la variable de referencia de la superclase.

4. ¿Qué son las Interfaces? Las interfaces son similares a las clases, en términos de sintaxis, pero no soportan ninguna variable de instancia. Una interfaz esencialmente captura los roles que juegan las diferentes clases que implementan las interfaces. Una interfaz especifica el prototipo o comportamiento de una clase. Todos los métodos declarados en una interfaz son métodos abstractos, es decir, no se les proporciona implementación. Una interfaz no puede ser instanciada. Tanto las clases abstractas como las concretas pueden

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 195

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

implementar una interfaz. Una clase concreta que implemente la interfaz tiene que proveer la implementación para todos los métodos declarados en la interfaz.

Si la implementación no se proporciona para aunque sea uno de los métodos definidos en la interfaz entonces la clase deber ser declarada como clase abstracta.

Una clase puede implementar cualquier número de interfaces. También una misma interfaz puede ser implementada por cualquier número de clases. Las interfaces implementadas por una clase especifican la interfaz que puede ser usada para la comunicación entre la clase y otros objetos. Una interfaz puede extender de otra interfaz, lo que significa que se puede crear una jerarquía de interfaces. Sin embargo, una interfaz no puede implementar otra interfaz, ya que la implementación no es provista por ninguno de los métodos declarados en la interfaz.

Clases no relacionadas pueden implementar la misma interfaz, introduciéndose cierta relación entre las clases, ésta es una de las ventajas de usar interfaces. Todas las funcionalidades requeridas por diferentes aplicaciones se guardan dentro de una interfaz. Por lo tanto, las interfaces actúan como sustitutos de la herencia múltiple.

La definición de interfaz es similar a la definición de clases. La estructura general se muestra a continuación:

modificadorDeAcceso interface nombreInterfaz { tipoDeDato nombreVar1 = valor;

tipoDeDato nombreVar2 = valor;

.

.

.

tipoDeDato nombreVarN = valor;

tipoDeRetorno nombreMetodo1(listaDeArgumentos);

tipoDeRetorno nombreMetodo2(listaDeArgumentos);

.

.

.

tipoDeRetorno nombreMetodoN(listaDeArgumentos);

}

Usualmente, el modificadorDeAcceso usado es public, de lo contrario no es mencionado. Cuando el modificadorDeAcceso no se menciona, se considera package por defecto. Cuando una interfaz se declara como public, cualquier otra interfaz o clase presente en cualquier paquete puede usarla.

El nombre de una interfaz se especifica en nombreInterfaz, que es un identificador válido. Las interfaces pueden declarar variables que son final y static. De tal forma que, las clases que implementen la interfaz no pueden cambiar sus valores. Las

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 196

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

variables definidas en una interfaz deben ser inicializadas con un valor constante. Si la interfaz se declara como public, todas las variables y métodos en la interfaz tienen acceso público.

Considere la Figura 5.8, que muestra la definición de la interfaz List de Java 1.4.

Figura 5.8: Definición de la Interfaz List en Java 1.4

La Figura 5.8 muestra la interfaz List definida en el paquete java.util, que es parte del marco de trabajo para colecciones de Java. Se discute el marco de trabajo para colecciones en el Volumen 8, Unidad 1 – API Colecciones. Esta figura sólo muestra algunos de los métodos más usados de la interfaz List.

La Figura 5.9 presenta la definición de la interfaz List de java 1.4 en formato UML (Unified Modeling Language). UML es un lenguaje de modelación para el análisis y diseño orientado a objetos.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 197

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 5.9: Definición de la interfaz List en Formato UML

UML hace uso del estereotipo <<interface>> para indicar que List es una interfaz y no una clase.

La Figura 5.10 muestra la clase Vector, que implementa la interfaz List.

Figura 5.10: Definición de la Clase Vector que Implementa la Interfaz List

La Figura 5.11 muestra la representación en UML para la clase Vector, que implementa la interfaz List. En esta figura, se puede ver una línea punteada seguida

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 198

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

por un triangulo hueco, esta es la notación UML para indicar que Vector implementa la interfaz List.

Dos otras clases, LinkedList y ArrayList, implementan también List. De manera que si se entiende la interfaz List, se puede fácilmente entender la operación de las clases Vector, LinkedList y ArrayList.

Figura 5.11: Representación UML de la Clase Vector que Implementa List

No es obligatorio para los métodos definidos en una interfaz usar la palabra reservada abstract, ya que todos los métodos definidos en una interfaz son abstractos por definición.

El siguiente código da un ejemplo de declaración de interfaz:

interface ContestadorAutomatico {

void grabarMensaje(String mensaje);

String getMensajeGrabado();

}

Esta es una declaración simple de interfaz con dos métodos, getMensajeGrabado() y grabarMensaje() en ella. Se debe notar que la implementación de los métodos no se proporciona aquí. Las clases que implementen esta interfaz deben proporcionar la implementación de los métodos. A continuación se entenderá por qué se usan las interfaces.

4.1 ¿Por qué usar Interfaces?

En la sección anterior, se aprendió que la clase Vector implementa la interfaz List. También se sabe que la clase Vector puede contener toda la funcionalidad que provee la interfaz List, sin tener que implementar la interfaz. Las funcionalidades pueden ser implementadas como métodos en la clase Vector. Se escoge implementar la interfaz como una mejor alternativa porque las interfaces definen un protocolo. Una interfaz puede ser implementada por muchas clases, así, se asegura que todas las clases que implementan la interfaz se adhieren al protocolo definido en la interfaz. Una clase

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 199

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Vector, una clase HashTable y cualquier otra clase que requiera el protocolo definido en la interfaz List puede implementar la interfaz List. Los usuarios de estas clases saben que todas las clases que implementen la interfaz List proveerán los métodos add, contains, get, remove, isEmpty etc., porque la interfaz List declara estos métodos.

4.2 Implementación de Interfaces

En la sección previa, se aprendió a declarar una interfaz. Una vez que la declaración de la interfaz se completa, puede ser implementada por una clase. La clase usa la cláusula implements para especificar las interfaces que implementa. Si la clase implementa múltiples interfaces, los nombres de las interfaces se separan por comas.

Si dos o más interfaces implementadas por una clase tienen la misma declaración de método, la clase sólo necesita proveer una implementación para la declaración del método. Los métodos que implementan las clases deben ser declarados como public y sus firmas del método deben coincidir con la firma del método declarado en la interfaz que ellas implementan.

La siguiente es la estructura general de la declaración de clase para la clase que implementa una interfaz:

modificadorDeAcceso class nombreClase [extends nombreSuperClase] [implements interfaz1, interfaz2, ...] {

// cuerpo de la clase

}

Considere el Ejemplo 5.3 para entender cómo una clase implementa una interfaz.

Ejemplo 5.3

El ejemplo muestra como la clase Telefono implementa la interfaz ContestadorAutomatico antes mencionada.

El código Java comienza aquí…

1. /* Definicion de la clase Telefono comienza aqui */

2. public class Telefono implements ContestadorAutomatico{ 3. String mensaje;

4. String mensajeSaludo = "Regreso despues de las 11pm";

5.

6. /* El metodo grabarMensaje comienza aqui */

7. public void grabarMensaje(String mensaje) {

8. System.out.println("Mensaje grabado: " + mensaje);

9. this.mensaje = mensaje;

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 200

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

10. }/* El metodo grabarMensaje termina aqui */ 11. 12. /* El metodo getMensajeGrabado comienza aqui */ 13. public String getMensajeGrabado() { 14. System.out.println("Mensaje Saludo: " + mensajeSaludo); 15. return mensajeSaludo; 16. }/* El metodo getMensajeGrabado termina aqui */ 17. }/* Definicion de la clase Telefono termina aqui */

El código Java termina aquí

Se debe notar que los métodos en la clase anterior Telefono se declaran como public dado que implementan los métodos de la interfaz ContestadorAutomatico. El ejemplo anterior, muestra a la clase Telefono implementando los dos métodos declarados en la interfaz ContestadorAutomatico. Cuando se observa la declaración de la clase Telefono, se sabe que implementa la interfaz ContestadorAutomatico, lo que asegura que los dos métodos declarados en ContestadorAutomatico serán implementados.

También es posible que la clase Telefono desee definir otras funcionalidades además de los métodos declarados en la interfaz, esto se ilustra en el siguiente extracto de código:

El código Java comienza aquí…

1. /* Definicion de la clase Telefono comienza aqui */

2. public class Telefono implements ContestadorAutomatico{

3. String mensaje;

4. String mensajeSaludo = "Regreso despues de las 11pm";

5. String mensajeBasico = "Hola";

6. String mensajeInterlocutor1;

7. String mensajeInterlocutor2;

8. boolean interlocutor1 = false;

9. boolean interlocutor2 = false;

10. boolean respuestaEncendido = false; 11. // . . . 12. 13. /* El metodo grabarMensaje comienza aqui */ 14. public void grabarMensaje(String mensaje) { 15. System.out.println("Mensaje grabado: " + mensaje); 16. this.mensaje = mensaje;

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 201

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

17. }/* El metodo grabarMensaje termina aqui */ 18. 19. /* El metodo getMensajeGrabado comienza aqui */ 20. public String getMensajeGrabado() { 21. System.out.println("Mensaje Saludo: " + mensajeSaludo); 22. return mensajeSaludo; 23. }/* El metodo getMensajeGrabado termina aqui */ 24. 25. /* El metodo recibirMensajeInterlocutor1 comienza aqui */ 26. String recibirMensajeInterlocutor1() { 27. return(mensajeInterlocutor1); 28. }/* El metodo recibirMensajeInterlocutor1 termina aqui */ 29. 30. /* El metodo enviarMensajeInterlocutor1 comienza aqui */ 31. void enviarMensajeInterlocutor1(String mensaje) { 32. mensajeInterlocutor2 = mensaje; 33. }/* El metodo enviarMensajeInterlocutor1 termina aqui */ 34. 35. /* El metodo recibirMensajeInterlocutor2 comienza aqui */ 36. String recibirMensajeInterlocutor2() { 37. return(mensajeInterlocutor2); 38. }/* El metodo recibirMensajeInterlocutor2 termina aqui */ 39. 40. /* El metodo enviarMensajeInterlocutor2 comienza aqui */ 41. void enviarMensajeInterlocutor2(String mensaje) { 42. mensajeInterlocutor1 = mensaje; 43. }/* El metodo enviarMensajeInterlocutor2 termina aqui */ 44. }/* Definicion de la clase Telefono termina aqui */

El código Java termina aquí

El segmento de código anterior muestra que la clase Telefono tiene otros métodos, son estos, recibirMensajeInterlocutor1(), enviarMensajeInterlocutor1(), etc.

Fin del Ejemplo 5.3

A continuación se muestra cómo se usa una referencia a una interfaz.

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 202

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

5. Usar Interfaces Como Referencias Se ha visto como declarar una variable que referencia a un objeto de una clase. Similarmente, se puede tener una variable de tipo interfaz, que referencia a una instancia de una clase que implementa esa interfaz. Considere el Ejemplo 5.4.

Ejemplo 5.4

El ejemplo muestra como se usa una referencia a una interfaz.

El código Java comienza aquí…

1. /* Definicion de la clase InterfazEjemplo comienza aqui */

2. public class InterfazEjemplo {

3. /* El metodo main comienza aqui */

4. public static void main(String[] args) {

5. String mensaje;

6. ContestadorAutomatico ca = new Telefono();

7. mensaje = ca.getMensajeGrabado();

8. ca.grabarMensaje("Llegare a las 11am – Pedro");

9. System.out.println("Mensaje recibido: " + mensaje);

10. }/* El metodo main termina aqui */

11. }/* Definicion de la clase InterfazEjemplo termina aqui */

El código Java termina aquí

La salida de este programa es la siguiente:

Mensaje Saludo: Regreso despues de las 11pm

Mensaje grabado: Llegare a las 11am – Pedro

Mensaje recibido: Regreso despues de las 11pm

En este programa, a pesar que la variable ca se declara del tipo de la interfaz ContestadorAutomatico, se le asigna el objeto de la clase Telefono. La variable ca sólo puede usarse para acceder a los métodos definidos por la interfaz ContestadorAutomatico.

Cualquier otro método definido en la clase Phone no puede ser accedido por la variable ca, a pesar de que es asignado el objeto de la clase Telefono. El programa dado no ilustra el poder polimórfico de una variable de referencia de interfaz. Esto se muestra en el siguiente código:

El código Java comienza aquí…

1. /* Definicion de la clase Telefono2 comienza aqui */

2. class Telefono2 implements ContestadorAutomatico{

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 203

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

3. String mensaje;

4. String mensajeSaludo = "Regreso despues de 1 hora";

5. // . . .

6.

7. /* El metodo grabarMensaje comienza aqui */

8. public void grabarMensaje(String mensaje) {

9. System.out.println(

10. "Mensaje grabado en Telefono2: " + 11. mensaje); 12. this.mensaje = mensaje; 13. }/* El metodo grabarMensaje termina aqui */ 14. 15. /* El metodo getMensajeGrabado comienza aqui */ 16. public String getMensajeGrabado() { 17. System.out.println( 18. "Mensaje Saludo de Telefono2: " + 19. mensajeSaludo); 20. return mensajeSaludo; 21. }/* El metodo getMensajeGrabado termina aqui */ 22. }/* Definicion de la clase Telefono2 termina aqui */ 23. 24. /* Definicion de la clase InterfazEjemplo2 comienza aqui */ 25. public class InterfazEjemplo2 { 26. /* El metodo main comienza aqui */ 27. public static void main(String[] args) { 28. String mensaje; 29. ContestadorAutomatico ca = new Telefono(); 30. 31. mensaje = ca.getMensajeGrabado(); 32. System.out.println("Mensaje recibido: " + mensaje); 33. ca.grabarMensaje("Nos encontramos a las 11am – Pedro"); 34. 35. Telefono2 t2 = new Telefono2(); 36. ca = t2; 37. mensaje = ca.getMensajeGrabado(); 38. System.out.println("Mensaje recibido: " + mensaje); 39. ca.grabarMensaje("Nos encontramos a la 1 pm – David");

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 204

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

40. }/* El metodo main termina aqui */ 41. }/* Definicion de la clase InterfazEjemplo2 termina aqui */

El código Java termina aquí

La salida del programa es la siguiente:

Mensaje Saludo: Regreso despues de las 11pm

Mensaje recibido: Regreso despues de las 11pm

Mensaje grabado: Nos encontramos a las 11am – Pedro

Mensaje Saludo de Telefono2: Regreso despues de 1 hora

Mensaje recibido: Regreso despues de 1 hora

Mensaje grabado en Telefono2: Nos encontramos a la 1 pm – David

Del programa anterior se puede ver que la versión de la implementación de ContestadorAutomatico llamada depende del tipo de objeto al que la variable ca esté haciendo referencia en tiempo de ejecución.

Fin del Ejemplo 5.4

Cuando una clase implementa una interfaz, puede escoger proveer implementación sólo para algunos de los métodos declarados en la interfaz. Esta clase entonces debe ser declarada como una clase abstracta, ya que sólo se realiza una implementación parcial de la interfaz. Se muestra esto con un ejemplo.

Ejemplo 5.5

Este ejemplo ilustra como una clase que provee implementación parcial de una interfaz, resulta en una clase abstracta.

El código Java comienza aquí…

1. /* Definicion de la clase Telefono3 comienza aqui */

2. abstract public class Telefono3 3. implements ContestadorAutomatico {

4.

5. String mensajeSaludo = "Regreso despues de 1 hora";

6.

7. /* El metodo getMensajeGrabado comienza aqui */

8. public String getMensajeGrabado() {

9. System.out.println(

10. "Mensaje Saludo de Telefono3: " + 11. mensajeSaludo); 12. return mensajeSaludo;

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 205

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

13. }/* El metodo getMensajeGrabado termina aqui */ 14. }/* Definicion de la clase Telefono3 termina aqui */

El código Java termina aquí

La clase Telefono3 implementa sólo el método getMensajeGrabado() de la interfaz ContestadorAutomatico. No implementa el método grabarMensaje() que está definido en la interfaz ContestadorAutomatico. Como Telefono3 sólo da una implementación parcial de la interfaz ContestadorAutomatico, debe declararse como una clase abstracta.

Fin del Ejemplo 5.5

Se discute a continuación qué son las interfaces marcadoras.

5.1 Interfaces Marcadoras

Las interfaces marcadoras son interfaces vacías sin ninguna declaración de variables o métodos. Una clase que implemente una interfaz marcadora no necesita implementar ningún método, y no tiene acceso a ninguna variable declarada como final en la interfaz, porque ninguna existe. La clase sólo necesita usar la palabra clave implements, seguida por el nombre de la interfaz marcadora, en su definición de clase. Esto permite que la clase tenga la funcionalidad para la cual se define la interfaz. Serializable y Cloneable son ejemplos de interfaces marcadoras. Si una clase implementa la interfaz Serializable, sus objetos pueden ser serializados y deserializados. Si una clase implementa la interfaz Cloneable, puede crear clones (copias exactas) de objetos de la clase.

A continuación se explica cómo crear una jerarquía de interfaces.

6. Heredar de una Interfaz Se puede crear una jerarquía de interfaces (similar a una jerarquía de clases), en la cual una interfaz puede heredar de otra interfaz usando la palabra reservada extends. Una clase no puede heredar de una interfaz. Sólo una interfaz puede heredar de otra interfaz. Considere el Ejemplo 5.6 que consta de un programa Java que extiende una interfaz de una interfaz existente. La interfaz derivada añade sus propias variables y métodos.

Ejemplo 5.6

Este ejemplo muestra como una interfaz se extiende de una interfaz existente y añade variables y métodos. Asuma que una interfaz K extiende de una interfaz J. Entonces, K implícitamente obtiene todas las variables y métodos declarados en J. K puede añadir sus propias variables y métodos a las que ha heredado de J.

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 206

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

El código Java comienza aquí…

1. interface J {

2. void metodo1();

3. void metodo2();

4. }

5.

6. interface K extends J {

7. void metodo3();

8. void metodo4();

9. }

10. 11. interface L extends K { 12. void metodo4(); 13. void metodo6(); 14. } 15. 16. interface M { 17. void metodo6(); 18. } 19. 20. /* Definicion de la clase InterfazEjemplo comienza aqui */ 21. class InterfazPrueba implements L, M { 22. /* El metodo metodo1 comienza aqui */ 23. public void metodo1() { 24. System.out.println("Dentro de metodo1"); 25. }/* El metodo metodo1 termina aqui */ 26. 27. /* El metodo metodo2 comienza aqui */ 28. public void metodo2() { 29. System.out.println("Dentro de metodo2"); 30. }/* El metodo metodo2 termina aqui */ 31. 32. /* El metodo metodo3 comienza aqui */ 33. public void metodo3() { 34. System.out.println("Dentro de metodo3"); 35. }/* El metodo metodo3 termina aqui */ 36.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 207

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

37. /* El metodo metodo4 comienza aqui */ 38. public void metodo4() { 39. System.out.println("Dentro de metodo4"); 40. }/* El metodo metodo4 termina aqui */ 41. 42. /* El metodo metodo6 comienza aqui */ 43. public void metodo6() { 44. System.out.println("Dentro de metodo6"); 45. }/* El metodo metodo6 termina aqui */ 46. }/* Definicion de la clase InterfazEjemplo termina aqui */ 47. 48. /* Definicion de la clase InterfazEjemplo comienza aqui */ 49. public class InterfazEjemplo { 50. /* El metodo main comienza aqui */ 51. public static void main(String[] args) { 52. InterfazPrueba ip = new InterfazPrueba(); 53. ip.metodo1(); 54. ip.metodo2(); 55. ip.metodo3(); 56. ip.metodo4(); 57. ip.metodo6(); 58. }/* El metodo main termina aqui */ 59. }/* Definicion de la clase InterfazEjemplo termina aqui */

El código Java termina aquí

La salida del programa anterior es la siguiente:

Dentro de metodo1

Dentro de metodo2

Dentro de metodo3

Dentro de metodo4

Dentro de metodo6

En este programa, se ve que la interfaz K y la interfaz L declaran el mismo método metodo4, a pesar que la interfaz L hereda el metodo4 definido por K. Esto es similar a sobrescribir métodos en el caso de clases. La clase InterfazPrueba implementa las interfaces L y M. Esta clase tiene que proporcionar la implementación de los métodos metodo1, metodo2, metodo3, metodo4 y metodo6, ya que la interfaz L declara implícitamente todos los métodos anteriores, dado que los hereda de las interfaces J y K. Tanto la interfaz L como M declaran el método metodo6, sin embargo

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 208

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

la clase InterfazPrueba tiene que proporcionar sólo una implementación del método metodo6, de otro modo ocurre un error de compilación (duplicate method declaration error). En caso de que la clase InterfazPrueba no proporcione implementación para alguno de los métodos declarados en las interfaces que implementa, entonces tiene que ser declarada como abstracta.

Fin del Ejemplo 5.6

Una vez discutidas las clases concretas, abstractas y las interfaces, se van a resumir las opciones de herencia en Java.

7. Opciones de Herencia en Java Existen tres tipos de opciones de herencia en Java:

• Herencia con clases concretas. • Herencia con clases abstractas. • “Herencia” Implementación de interfaces.

La Figura 5.12 ilustra las tres opciones de herencia.

Figura 5.12: Opciones de Herencia en Java

Cuando una clase hereda de otra clase concreta, usa la palabra clave extends. La superclase concreta puede ser instanciada y además debe implementar todos los métodos definidos en ella. La superclase concreta puede tener variables de instancia definidas en ella.

Cuando una clase hereda de una clase abstracta, usa la palabra reservada extends. La superclase abstracta no puede ser instanciada, puede proveer implementación para algunos de los métodos definidos en ella, aunque no se requiere que proporcione implementaciones para ninguno de sus métodos. La superclase abstracta puede tener variables de instancia definidas en ella.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 209

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Cuando una clase implementa una interfaz, usa la palabra reservada implements. Una clase puede implementar múltiples interfaces. La interfaz no puede ser instanciada y no provee implementación para ninguno de los métodos en ella. La interfaz no puede definir variables de instancia.

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 210

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Resumen Ahora que ha completado esta unidad, usted debe ser capaz de:

• Diferenciar entre herencia y agregación. • Discutir sobre clases abstractas. • Diferenciar entre clases abstractas y clases concretas. • Describir cómo se definen las clases y métodos abstractos en Java. • Definir una interfaz. • Explicar cómo las interfaces son implementadas y usadas como referencias.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 211

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 5: Examen de Autoevaluación 1) ¿Cuál de las siguientes opciones es falsa acerca de los métodos abstract?

a) Pueden ser accedidos directamente sin crear un objeto de la clase que los contiene.

b) No se proporciona su implementación. c) Su implementación es proporcionada por sus subclases. d) Nunca pueden ser invocados.

2) Una clase abstracta debe contener al menos un método abstracto.

a) Verdadero b) Falso

3) ¿Cuál de las siguientes es la forma correcta para crear una referencia a una clase

abstracta X? a) X x; x = new X(); b) X x = new X(); c) X x; d) Ninguna de las anteriores

4) La variable de referencia que hace referencia a una clase abstracta puede ser

inicializada con _______. a) Un objeto de la clase abstracta b) Un objeto de la subclase de la clase abstracta c) La clase abstracta d) La subclase de la clase abstracta

5) Los métodos abstract de clases pueden estar presentes sólo dentro de una

clase abstract. a) Verdadero b) Falso

6) ¿Cuál de las siguientes son las maneras correctas de declarar una interfaz?

a) public class X implements interface {} b) public interface X {} c) interface X{} d) public X implements interface {}

Core Java Guía del Estudiante

Unidad 5: Clases Abstractas e Interfaces Libro 1: Core Java 212

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

7) Las interfaces pueden declarar métodos abstract. a) Verdadero b) Falso

8) ¿Cuál de las siguientes es sintácticamente correcta cuando se implementa una

interfaz X que declara dos métodos void m1() y m2()? a) class Y extends X {

public void m1() {}

public void m2() {}

}

b) class Y implements X { public void m1() {}

}

c) class Y extends X { void m1() {}

}

d) class Y implements X { public void m1() {}

public void m2() {}

}

9) Implícitamente, todas las variables en una interfaz son de la forma final y static. a) Verdadero b) Falso

10) ¿Cuál de las siguientes opciones es falsa acerca de una interfaz?

a) Es posible crear una jerarquía de interfaces. b) Una variable de tipo interfaz puede hacer referencia a un objeto de la clase

que la implementa c) Una interfaz que contenga un método abstract declarado en ella no debe

tener el modificador abstract en su declaración. d) Las interfaces pueden ser instanciadas.

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 213

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Respuestas a la Unidad 5: Examen de Autoevaluación 1) a 2) b 3) c 4) b 5) a 6) b y c 7) a 8) d 9) a

10) d

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 215

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 6: Laboratorio de Clases Abstractas e Interfaces

Objetivos de Aprendizaje Al final de esta unidad, usted será capaz de:

• Usar clases abstractas. • Usar interfaces.

Core Java Guía del Estudiante

Unidad 6: Laboratorio de Clases Abstractas e Interfaces Libro 1: Core Java 216

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Ejercicios de Laboratorio

1) Escribir un programa en Java que tenga una clase abstracta llamada Fotografia y una interfaz llamada Clicking. La interfaz Clicking tiene los siguientes métodos en ella. Escena marcoFoto(Escena);

Escena focoFoto(Escena);

Camara setAbertura(Camara);

Camara setVelocidadObturador(Camara);

Camara setVelocidadPelicula(Camara);

• La clase Escena tiene los atributos ancho, alto, coordenadaX y coordenadaY. Tiene los métodos:

void setAncho(int ancho);

void setAlto(int alto);

void setXCoordenada(int xcoord);

void setYCoordenada(int ycoord);

void setEnfoque(int enfoque);

• La clase Camara tiene los atributos abertura, velocidadObturador, velocidadSyn y velocidadPelicula. Tiene el método:

public static void setVelocidadSyn(int velocidadSyn);

int aberturaPrioridad(int abertura); // el int retornado es usado para establecer velocidadObturador

int velocidadObturadorPrioridad(int velocidadObturador); // el int retornado es usado para establecer abertura

• Dos clases llamadas Canon y Nikon heredan de la clase Camara. La clase Nikon tiene el método:

void buenaAfinacionVelocidadObturador(int velocidadObturador);

La clase Canon tiene el método, void buenaAfinaciónAbertura(int abertura);

• La clase Fotografia tiene los atributos escena, claridad, contraste y enfoque y tiene los siguientes métodos:

// No se proporciona implementación

abstract Escena capturaEscena(Escena);

void setEnfoque(int enfoque);

void setClaridad(int claridad);

void setContraste(int contraste);

Guía del Estudiante Core Java

Libro 1: Core Java Volumen 2: Programación Orientada a Objetos 217

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

• La clase MiFotografia hereda de Fotografia. La clase Fotografo implementa la interfaz Clicking y usa las clases mencionadas para tomar una fotografía.

• Cree una clase Prueba para verificar el funcionamiento de la Camara y el método de Fotografia.

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 219

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 7: Paquetes

Objetivos de Aprendizaje Al final de esta unidad, usted será capaz de:

• Definir y crear un paquete. • Explicar cómo se representan los paquetes en el sistema de archivos. • Discutir las protecciones de acceso en los paquetes. • Describir los miembros de los paquetes. • Discutir cómo importar paquetes. • Explicar las variables classpath y describir su uso. • Explicar los paquetes más usados que vienen incorporados con Java.

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 220

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

1. Introducción En la unidad anterior, se explicaron las clases abstractas e interfaces en Java. En esta unidad se aprenderá acerca de cómo las clases e interfaces pueden ser agrupadas usando el concepto de paquetes.

Los paquetes son un medio para agrupar clases, interfaces y otros paquetes en una categoría particular.

Un paquete Java es como un directorio, permite de una manera segura almacenar una clase dentro de él.

Un paquete es un contenedor que almacena la funcionalidad relacionada con clases e interfaces y otros paquetes, proporcionando acceso protegido y manejo de nombres de espacio. Un paquete es básicamente un mecanismo provisto por Java que ayuda a dividir el espacio de nombre de clase en bloques manejables. Es un mecanismo de denominación así como de control de visibilidad. Un paquete no puede tener dos clases con el mismo nombre.

Se va a explicar la necesidad del uso de los paquetes y las tareas involucradas en el uso de paquetes.

2. Necesidad de los Paquetes Existen varias razones por las cuales se necesita agrupar clases.

2.1 Conflictos de Nombres

Alrededor del mundo, muchos programadores desarrollan varias clases Java simultáneamente. Un programador puede no estar al tanto de las clases desarrolladas por otro programador. Por lo que dos o más programadores pueden desarrollar clases con el mismo nombre. Existe entonces la posibilidad de un conflicto de nombres entre clases desarrolladas por diferentes programadores. Considere la Figura 7.1, donde se muestran dos conjuntos de librerías que tienen ambas una clase Texto, y una aplicación MiAplicacion usa ambas librerías.

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 221

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 7.1: Conflictos de Nombres en Aplicaciones

Cuando se usa la clase Texto en MiAplicacion, el sistema de tiempo de ejecución de Java no sabrá a cual clase llamar. Para evitar estos conflictos de nombres, las clases desarrolladas por un programador para una aplicación específica pueden ser agrupadas bajo un cierto paquete.

Los paquetes Java son similares a los nombres de espacio usados en C++. Ellos eliminan los conflictos de nombres. Asuma que dos librerías diferentes, A y B, tienen el mismo nombre de clase X. Si se le asigna a cada clase a un paquete diferente, no se tendrán conflictos de nombres entre las dos librerías.

Las clases se identifican por nombres de paquete, seguidas por el nombre de la clase en un programa Java. Una clase Documento, por ejemplo en un paquete p se identifica como p.Documento.

2.2 Clasificación

Suponga que se tiene que desarrollar varias aplicaciones Java. Se deben crear clases para realizar operaciones matemáticas y operaciones de transferencias de archivos para estas aplicaciones. Por lo tanto, puede ser útil agrupar todas las clases relacionadas a las funciones matemáticas en un paquete y agrupar todas las clases relacionadas con las transferencias de archivos en otro paquete. Este tipo de clasificación no solo nos ayudará a localizar una clase fácilmente, sino que permitirá en forma fácil reutilizar clases entre las aplicaciones Java.

2.3 Despliegue

Asuma que se tiene que desarrollar una aplicación y entregarla al cliente. La aplicación completa comprende varios módulos y por tanto se tendrán muchos archivos de clases (.class). Todas las clases requeridas para desplegar un componente en particular de la aplicación pueden ser agrupadas bajo un paquete determinado, esto ayudará al despliegue de los componentes fácilmente.

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 222

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

2.4 Alcance de Clases Restringido

A veces se quiere encapsular ciertos datos importantes usados por una aplicación. Para esto, se tiene que restringir el acceso a las clases que mantienen estos datos. En este caso, se pueden agrupar todas las clases que mantienen datos en un paquete, y dar acceso de paquete a los datos. Esto restringirá a otras clases de acceder a los datos.

Para resumir, las ventajas provistas por los paquetes se representa en la Figura 7.2.

Figura 7.2: Ventajas de los Paquetes en Java

Ahora se procederá a ver como crear paquetes en Java.

3. Crear Paquetes en Java El primer paso en la creación de un paquete es asignarle un nombre que sea universalmente único. Sin embargo, asignar un nombre aleatorio y esperar que sea

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 223

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

universalmente único no es buena idea, hay ciertos lineamientos que deben seguirse para nombrar un paquete.

3.1 Nombrar un Paquete

Las guías para nombrar un paquete son:

• Los nombres de los paquetes deben ser jerárquicos. El nombre puede contener más de una parte separada por puntos.

• El nombre de paquete debe comenzar con el nombre de dominio Internet en reversa. Por ejemplo, las librerías de clases que provee IBM tiene paquetes que comienzan por com.ibm.

• Después se añade el nombre del departamento interno al cual el paquete pertenece. Por ejemplo, IBM Learning Services (ILS) se añade a com.ibm. Ahora el nombre del paquete es com.ibm.ils.

• Después, el nombre de la aplicación se añade al nombre del paquete. Por ejemplo, com.ibm.ils.examen.

Nota: El nombre del paquete no tiene ninguna letra en mayúscula. Aunque se permiten las letras mayúsculas, es por convención el tener todas las letras en minúsculas.

En el ejemplo anterior, el paquete exam puede contener varias clases o interfaces relacionadas funcionalmente. Puede existir otro paquete dentro de ils llamado monitor. Este llevará el nombre de com.ibm.ils.monitor. Así, ambos examen y monitor estarán al mismo nivel en la jerarquía de nombres del paquete.

3.2 Declaración de Paquetes

Un paquete es declarado con la palabra reservada package. Una declaración de paquete debe ser la primera instrucción en el archivo fuente Java cuando se crea un paquete. Usar la declaración de paquete al inicio del archivo asegura que todas las clases definidas dentro del archivo serán parte del paquete nombrado.

Una instrucción de paquete define un espacio de nombres para almacenar clases. Cuando la instrucción de paquete es eliminada del archivo, los nombres de clases son colocados en el paquete por defecto (default package). El paquete por defecto no tiene nombre y no es útil, por lo general, para aplicaciones finales. Se pueden usar el paquete por defecto para correr programas de prueba. La siguiente es la forma general de la instrucción de paquete:

package directorio;

En esta instrucción, el nombre del paquete creado es directorio. También, un programador puede crear una jerarquía de paquetes. Esto puede hacerse dividiendo el nombre del paquete desde el paquete superior de uno directamente por encima, usando un punto (.).

La siguiente es la forma de una instrucción de paquete multinivel:

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 224

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

package directorio.lista.miembros;

Cuando se especifica un nombre de paquete en un archivo, todas las clases definidas en el archivo pertenecen al paquete especificado. No es obligatorio tener una instrucción de paquete antes de toda definición de clase. Sin embargo, un archivo solamente puede tener una instrucción de paquete.

Dentro de un programa Java, la instrucción de paquete aparece antes de las instrucciones import, que se usan para importar las clases requeridas por la aplicación, como se muestra en la Figura 7.3.

Figura 7.3: Declaración de Paquete en un Archivo Java

En la Figura 7.3, el paquete com.ibm.ils.examen.dominio contiene la clase PreguntaExamen. La figura ilustra solo una clase en el paquete. Sin embargo, puede haber más de una clase definida en un paquete. Todas las clases definidas, entonces, pertenecen al mismo paquete com.ibm.ils.examen.dominio.

A continuación se discute como los paquetes se representan en el sistema de archivos.

4. Representación del Paquete en el Sistema de Archivos Los paquetes se almacenan usualmente en directorios del sistema de archivos. Ellos están directamente relacionados a la estructura física de las carpetas. Por ejemplo, considere la clase C, que pertenece a un paquete, x.y a través de la siguiente instrucción:

package x.y;

public class C {

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 225

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

}

La clase C es compilada y colocada en la carpeta X\Y\ bajo algún directorio en el sistema, por ejemplo:

C:\Ejemplos\x\y\C.class

Así, los paquetes corresponden a la estructura física de carpetas. Una excepción a esto es cuando las clases son empaquetadas dentro de archivos JAR. Se aprenderá acerca de archivos JAR en la Unidad 9 – Características Avanzadas del Volumen 8.

El nombre del directorio debe coincidir con el nombre del paquete letra por letra. Esta correspondencia es sensible a mayúsculas y minúsculas.

Más de un archivo puede incluir la misma instrucción de paquete, porque la instrucción de paquete simplemente indica donde las clases definidas pertenecen, y no evita que otras clases en otros archivos pertenezcan al mismo paquete. Las clases en los desarrollos del mundo real están usualmente repartidas en varios archivos. Por ejemplo, considere el siguiente fragmento de código:

package x.y;

public class AA {

}

class BB {

}

class CC {

}

Este código se almacenará en un archivo llamado AA.class, que es diferente del anterior C.class, pero ambos tienen la misma instrucción de paquete al comienzo, y AA.class estará presente en la carpeta física C:\Ejemplos\x\y\. Así, es posible tener cualquier número de archivos con diferentes definiciones de clases perteneciendo al mismo paquete. Todo lo que se necesita es el mismo nombre de paquete al inicio del archivo.

Los paquetes pueden ser comparados a los directorios usados para almacenar archivos en el sistema de archivos de un sistema de operativo. En el sistema de archivos, es posible tener subdirectorios dentro de un directorio. Pueden existir subdirectorios con el mismo nombre bajo diferentes directorios. Sin embargo, no se pueden tener dos subdirectorios con el mismo nombre bajo un mismo directorio. Reglas similares son aplicables para los paquetes.

Considere la Figura 7.4, que representa los paquetes en el directorio en forma de árbol. El paquete representado en la figura es com.ibm.libreria.a, este paquete tiene dos archivos: Texto.java y Texto.class.

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 226

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 7.4: Representación de Paquete en el Sistema de Archivos

Asuma que hay un directorio llamado Root que tiene un subdirectorio llamado MiDirectorio, que a su vez tiene otro subdirectorio llamado MiSubDirectorio. Este subdirectorio tiene un archivo llamado miArchivo.txt. Se puede representar esta estructura como sigue:

Root\MiDirectorio\MiSubDirectorio\miArchivo.txt

Considere una estructura de paquete que tenga un paquete raíz com que tiene un subpaquete ibm, que a su vez tenga otro subpaquete libreria, con dos subpaquetes a y b. Esta estructura de paquete se puede representar como:

com.ibm.libreria.a

com.ibm.libreria.b

A continuación se estudia como referenciar a las clases definidas en los paquetes.

4.1 Referencia a las Clases Definidas en los Paquetes

En un programa Java, si se quiere usar una clase ubicada en un paquete en particular, se debe usar con el nombre completamente calificado, usando el nombre del paquete.

Considere dos clases, ambas llamadas Texto que están en dos paquetes diferentes, como se presenta a continuación:

com.ibm.libreria.a

com.ibm.libreria.b

Estas dos clases son distintas y pueden contener dos implementaciones diferentes. Se debe referir a estas clases dentro del programa Java, como sigue:

com.ibm.libreria.a.Texto

com.ibm.libreria.b.Texto

Esto se representa en la Figura 7.5.

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 227

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 7.5: Referencia a Clases por su Nombre de Paquete

El programador tiene que tener en cuenta que la jerarquía de paquete también tiene que ser mantenida en el sistema de archivos del desarrollo en Java.

Ahora, se estudiará como los paquetes ayudan a proteger el acceso a las clases.

5. Paquetes y Protección de Acceso Los paquetes y las clases son maneras de encapsular datos importantes. Los paquetes encapsulan varias clases y las clases encapsulan variables y métodos. Como hemos mencionado, los paquetes son receptáculos para las clases y los sub paquetes que son parte de él, mientras que las clases mantienen datos y código.

La visibilidad y la accesibilidad de los miembros de clase se ubican en una de las siguientes cuatro categorías:

• Sub-clases presentes en el mismo paquete. • No sub-clases presentes en el mismo paquete. • Sub-clases presentes en diferentes paquetes. • Clases no relacionadas presentes en diferentes paquetes.

Existen diversas formas de producir los diferentes niveles de acceso requeridos por las categorías antes descritas.

Los tres especificadores de acceso, private, public y protected, proveen los diferentes niveles de acceso. Cualquier miembro de clases declarado como public puede ser accedido desde cualquier sitio.

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 228

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Un miembro en una clase sin especificación de acceso explícita será visible a las subclases y otras clases dentro del mismo paquete. Cuando un elemento se declara protected, será visible fuera del paquete actual, pero sólo para las clases que son subclases de la clase actual. Cualquier miembro de clases declarado como private no será visto fuera de su clase. Estos modificadores de acceso aplican a los miembros de las clases.

Una clase (no anidada) solo tiene dos posibles niveles de acceso: default y public. Cuando no se indica el modificador de acceso en la declaración de la clase, implica que el nivel de acceso es el acceso por defecto. De aquí que todas las clases que son parte del paquete donde la clase esta presente, tienen acceso al código de esa clase. Si una clase es declarada como public, puede ser accedida por cualquier código fuera del paquete. No se puede declarar una clase (no anidada) como protected o private. Considere la Figura 7.6, donde se muestra un conjunto de clases en paquetes diferentes.

Figura 7.6: Clases en Paquetes Diferentes

En la figura anterior se definen cinco clases dentro de dos paquetes, com.ibm.ils.control y com.ibm.ils.modelo. Las clases A, B, y E están en com.ibm.ils.control y las clases C y D, en com.ibm.ils.modelo. La clase A tiene cuatro métodos con diferentes niveles de acceso, especificados por los modificadores de acceso public, protected y private. A continuación se explicará cuál de estos cuatro métodos puede ser accedido desde las clases A, B, C, D y E.

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 229

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

• Desde la clase A los cuatro métodos pueden ser accedidos: uno(), dos(), tres() y cuatro().

• Desde la clase B tres métodos pueden accederse: uno(), dos(), y tres(). • Desde la clase C dos métodos pueden accederse: uno() y dos(). • Desde la clase D solo un método puede accederse: uno(). • Desde la clase E tres métodos pueden accederse: uno(), dos(), y tres(). • Los métodos declarados como protected en la clase A pueden accederse por

clases que sean subclases de A.

Se presenta un ejemplo para entender mejor los especificadores de acceso.

Ejemplo 7.1

El siguiente programa ilustra el efecto de diferentes especificadores de acceso sobre clases en diferentes paquetes.

El código Java comienza aquí...

1. package paquete1;

2.

3. /* Definicion de la clase MiClase comienza aqui */

4. public class MiClase {

5. int variableDePaquete = 10;

6. private int variablePrivada = 20;

7. protected int variableProtegida = 30;

8. public int variablePublica = 40;

9.

10. /* Constructor MiClase comienza aqui */ 11. public MiClase() { 12. System.out.println( 13. "Dentro del constructor de MiClase"); 14. System.out.println( 15. "variableDePaquete = " + variableDePaquete); 16. System.out.println( 17. "variablePrivada = " + variablePrivada); 18. System.out.println( 19. "variableProtegida = " + variableProtegida); 20. System.out.println( 21. "variablePublica = " + variablePublica); 22. }/* Constructor MiClase termina aqui */ 23. }/* Definicion de la clase MiClase termina aqui */

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 230

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

24. package paquete1; 25. 26. /* Definicion de la clase comienza aqui */ 27. public class DeribadaDelMismoPaquete extends MiClase { 28. /* Constructor DeribadaDelMismoPaquete comienza aqui */ 29. public DeribadaDelMismoPaquete() { 30. System.out.println( 31. "Dentro del constructor de DeribadaDelMismoPaquete"); 32. 33. System.out.println( 34. "variableDePaquete = " + variableDePaquete); 35. 36. /* Las variables private son accesibles 37. * solo dentro de la misma clase */ 38. // System.out.println( 39. // "variablePrivada = " + variablePrivada); 40. 41. System.out.println( 42. "variableProtegida = " + variableProtegida); 43. 44. System.out.println( 45. "variablePublica = " + variablePublica); 46. }/* Constructor DeribadaDelMismoPaquete termina aqui */ 47. }/* Definicion de la clase termina aqui */

48. package paquete1; 49. 50. /* Definicion de la clase comienza aqui */ 51. public class SinRelacionDelMismoPaquete { 52. /* Constructor SinRelacionDelMismoPaquete comienza aqui */ 53. public SinRelacionDelMismoPaquete() { 54. MiClase mc = new MiClase(); 55. System.out.println( 56. "Dentro del constructor de " + 57. "SinRelacionDelMismoPaquete"); 58. 59. System.out.println(

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 231

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

60. "variableDePaquete = " + mc.variableDePaquete); 61. 62. /* Las variables private son accesibles 63. * solo dentro de la misma clase */ 64. // System.out.println( 65. // "variablePrivada = " + mc.variablePrivada); 66. 67. System.out.println( 68. "variableProtegida = " + mc.variableProtegida); 69. 70. System.out.println( 71. "variablePublica = " + mc.variablePublica); 72. }/* Constructor SinRelacionDelMismoPaquete termina aqui */ 73. }/* Definicion de la clase termina aqui */

74. package paquete2; 75. 76. import paquete1.*; 77. 78. /* Definicion de la clase comienza aqui */ 79. public class DeribadaDeDiferentePaquete extends MiClase{ 80. /* Constructor DeribadaDeDiferentePaquete comienza aqui */ 81. public DeribadaDeDiferentePaquete() { 82. System.out.println( 83. "Dentro del constructor de " + 84. "DeribadaDeDiferentePaquete"); 85. 86. /* Las variables Package son accesibles solo dentro 87. * de la misma clase o dentro del mismo paquete */ 88. //System.out.println( 89. // "variableDePaquete = " + variableDePaquete); 90. 91. /* Las variables private son accesibles 92. * solo dentro de la misma clase */ 93. // System.out.println( 94. // "variablePrivada = " + variablePrivada); 95. 96. System.out.println(

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 232

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

97. "variableProtegida = " + variableProtegida); 98. 99. System.out.println( 100. "variablePublica = " + variablePublica);

101. }/* Constructor DeribadaDeDiferentePaquete termina aqui */

102. }/* Definicion de la clase termina aqui */

103. package paquete2;

104.

105. import paquete1.*;

106.

107. /* Definicion de la clase comienza aqui */

108. public class SinRelacionDeDiferentePaquete {

109. /* Constructor SinRelacionDeDiferentePaquete comienza aqui*/

110. public SinRelacionDeDiferentePaquete() {

111. MiClase mc = new MiClase();

112. System.out.println(

113. "Dentro del constructor de " +

114. "SinRelacionDeDiferentePaquete");

115.

116. /* Las variables Package son accesibles solo dentro

117. * de la misma clase o dentro del mismo paquete */

118. //System.out.println(

119. // "variableDePaquete = " + mc.variableDePaquete);

120.

121. /* Las variables private son accesibles

122. * solo dentro de la misma clase */

123. // System.out.println(

124. // "variablePrivada = " + mc.variablePrivada);

125.

126. /* Las variables protected son accesibles dentro de

127. * la misma clase o dentro del mismo paquete o dentro

128. * de una la clase derivada */

129. //System.out.println(

130. // "variableProtegida = " + mc.variableProtegida);

131.

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 233

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

132. System.out.println(

133. "variablePublica = " + mc.variablePublica);

134. }/* Constructor SinRelacionDeDiferentePaquete termina aqui*/

135. }/* Definicion de la clase termina aqui */

136. package paquete1;

137.

138. /* Definicion de la clase MainPaquete1 comienza aqui */

139. public class MainPaquete1 {

140. /* El metodo main comienza aqui */

141. public static void main(String[] args) {

142. MiClase mc = new MiClase();

143. DeribadaDelMismoPaquete dmp =

144. new DeribadaDelMismoPaquete();

145. SinRelacionDelMismoPaquete srm =

146. new SinRelacionDelMismoPaquete();

147. }/* El metodo main termina aqui */

148. }/* Definicion de la clase MainPaquete1 termina aqui */

149. package paquete2;

150.

151. /* Definicion de la clase MainPaquete2 comienza aqui */

152. public class MainPaquete2{

153. /* El metodo main comienza aqui */

154. public static void main(String[] args) {

155. DeribadaDeDiferentePaquete ddp =

156. new DeribadaDeDiferentePaquete();

157. SinRelacionDeDiferentePaquete srd =

158. new SinRelacionDeDiferentePaquete();

159. }/* El metodo main termina aqui */

160. }/* Definicion de la clase MainPaquete2 termina aqui */

El código Java termina aquí

Al ejecutar el programa MainPaquete1.java se obtiene la siguiente salida:

Dentro del constructor de MiClase

variableDePaquete = 10

variablePrivada = 20

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 234

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

variableProtegida = 30

variablePublica = 40

Dentro del constructor de MiClase

variableDePaquete = 10

variablePrivada = 20

variableProtegida = 30

variablePublica = 40

Dentro del constructor de DeribadaDelMismoPaquete

variableDePaquete = 10

variableProtegida = 30

variablePublica = 40

Dentro del constructor de MiClase

variableDePaquete = 10

variablePrivada = 20

variableProtegida = 30

variablePublica = 40

Dentro del constructor de SinRelacionDelMismoPaquete

variableDePaquete = 10

variableProtegida = 30

variablePublica = 40

Al ejecutar el programa MainPquete2.java se obtiene la salida:

Dentro del constructor de MiClase

variableDePaquete = 10

variablePrivada = 20

variableProtegida = 30

variablePublica = 40

Dentro del constructor de DeribadaDeDiferentePaquete

variableProtegida = 30

variablePublica = 40

Dentro del constructor de MiClase

variableDePaquete = 10

variablePrivada = 20

variableProtegida = 30

variablePublica = 40

Dentro del constructor de SinRelacionDeDiferentePaquete

variablePublica = 40

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 235

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

De esta salida se puede ver que el constructor de la clase MiClase se invoca cada vez que una clase intenta acceder a sus variables, sea una subclase o una clase no relacionada.

Fin del Ejemplo 7.1

Se va a discutir a continuación cómo usar las clases definidas en el mismo paquete.

6. Usar Miembros de Paquetes Sólo los miembros públicos de un paquete son accesibles fuera del paquete en el que están definidos. Para acceder a un miembro público del paquete desde fuera de su paquete, se debe seguir alguno de los siguientes pasos:

• Referirse al miembro por su nombre completamente calificado como com.ibm.ils.examen.dominio, en vez de solo dominio

• Importar el miembro del paquete. • Importar el paquete completo del miembro.

Cada uno de los procedimientos dados se ajusta a un tipo particular de situación.

Usualmente, las clases son referidas por sus nombres cortos, es decir, el nombre especificado en su declaración. Estos nombres se pueden usar en situaciones donde la clase que se está usando está presente en el mismo paquete que la clase actual, o si el miembro del paquete se ha importado.

Sin embargo, considere una situación donde se quiere usar un miembro perteneciente a un paquete diferente, que no ha sido importado. En tales situaciones, el nombre largo del miembro debe usarse.

Considere una situación en la que se quiere usar la clase LinkedList, pero sin haber importado el paquete java.util.*. En ese caso, se tiene que usar el nombre largo de la clase LinkedList, como se muestra a continuación:

java.util.LinkedList ll = new java.util.LinkedList();

A pesar de que los nombres largos hacen a un programa más difícil de leer y escribir. Se puede solventar, a través del siguiente enfoque que se va a considerar donde se importan todas las clases definidas en un paquete en particular.

6.1 Importar un Paquete

Las clases estándar se almacenan en paquetes con nombres, ninguna clase estándar existe en el paquete por defecto. Si se quiere invocar a las clases con sus nombres de paquetes, se tiene que ingresar el nombre largo para cada clase. Para evitar esto, Java tiene la sentencia import, con lo que se puede referenciar ciertas clases, o inclusive paquetes enteros.

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 236

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Una vez que la clase es importada, puede ser referida directamente por su nombre. Debe tenerse en cuenta, sin embargo, que la sentencia import no es obligatoria para el programador, es un método conveniente de programación.

En un archivo fuente de Java, la instrucción import viene inmediatamente después de la instrucción package, y antes de cualquier definición de clase. A continuación se da la forma general de la instrucción import:

import paquete1[.paquete2].(nombreClase/*);

Aquí, paquete1 es el nombre del paquete de más alto nivel y paquete2, es un paquete subordinado dentro del paquete externo. La jerarquía de paquetes no tiene un límite de profundidad en la práctica, más que el que impone el sistema de archivos. Después de paquete2, un nombre de clase explícito o (*) se especifica. Esto indica que el compilador Java debe importar la clase especificada o el paquete completo. Puede usarse en cualquiera de las siguientes formas, como se muestra a continuación:

import java.util.Random;

o

import java.util.*;

En Java 5.0, se puede importar tanto las variables estáticas como los métodos estáticos que posee una clase. Esto nos ahorra colocar como prefijo el nombre de la clase que posee la variable o método estático. A continuación, se presenta un ejemplo.

Ejemplo 7.2

El siguiente programa ilustra el uso del import estático.

El código Java comienza aquí...

1. import static java.lang.Math.*;

2.

3. /* Definicion de la clase Principal comienza aqui */

4. public class Principal {

5. /* El metodo main comienza aqui */

6. public static void main(String[] args) {

7. System.out.print("PI(");

8. System.out.print(PI);

9. System.out.print(") elevado a la 2 es: ");

10. System.out.println(pow(PI, 2)); 11. }/* El metodo main termina aqui */ 12. }/* Definicion de la clase Principal termina aqui */

La salida del código anterior es esta:

PI(3.141592653589793) elevado a la 2 es: 9.869604401089358

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 237

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

El código Java termina aquí

Se puede ver que no fue necesario colocar la clase Math para hacer uso de la variable estática PI y del método estático pow.

Fin del Ejemplo 7.2

Un punto importante a tener en cuenta es que el uso del método asterisco import java.util.* puede incrementar el tiempo de compilación, a pesar de que no afecta en ninguna forma el rendimiento en tiempo de ejecución o el tamaño de la clase. Esto es especialmente cierto si el usuario tiene que importar grandes paquetes. Por lo tanto, puede ser mejor nombrar las clases a ser usadas en vez de importar paquetes completos.

Considere que se quiere usar las clases Vector y Random del paquete java.util. Como se discutió no será eficiente importar todas las clases del paquete java.util. En vez de eso, se pueden importar sólo las clases Vector y Random del paquete java.util, como se muestra a continuación:

import java.util.Vector;

import java.util.Random;

Todas las clases estándar incluidas en Java son guardadas en un paquete llamado java. Las funciones básicas del lenguaje son guardadas en otro paquete llamado java.lang. Usualmente, cada paquete/clase a ser usado tiene que ser importado, pero el compilador implícitamente importa java.lang para todos los programas. Esto es porque los programas Java, no pueden ejecutarse sin la funcionalidad de java.lang.

El formato general para importar java.lang se da a continuación:

import java.lang.*

Asuma que se quiere importar una clase cuyo nombre es el mismo que otra, existente en un paquete diferente. Considere el caso de la clase Date que está disponible en java.util y java.sql. Cuando las clases Date definidas en los dos paquetes se usa dentro del mismo programa, ocurre un conflicto de nombres. El compilador Java se confunde entre las dos clases. Para evitar esto, hay que referirse a estas dos clases a través de sus nombres completamente calificados, especificando también la jerarquía del paquete, como sigue:

java.util.Date

java.sql.Date

Observe el Ejemplo 7.3 para ver como el nombre del paquete se usa junto con el nombre de la clase durante la creación de una instancia de la clase.

Ejemplo 7.3

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 238

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Se usaran clases contenidas en diferentes paquetes para ilustrar lo que se discutió anteriormente.

El código Java comienza aquí...

1. package paquete1;

2.

3. /* Definicion de la clase A comienza aqui */

4. public class A {

5. String mensaje = "Clase en paquete1";

6. public A() {

7. System.out.println("Mensaje: " + mensaje);

8. }

9. }/* Definicion de la clase A termina aqui */

10. package paquete2; 11. 12. /* Definicion de la clase B comienza aqui */ 13. public class B { 14. String mensaje = "Clase en paquete2"; 15. public B() { 16. System.out.println("Mensaje: " + mensaje); 17. } 18. }/* Definicion de la clase B termina aqui */

19. package paquete3; 20. 21. import paquete1.A; 22. 23. /* Definicion de la clase Principal comienza aqui */ 24. public class Principal { 25. /* El metodo main comienza aqui */ 26. public static void main(String[] args) { 27. /* Uso del nombre largo de la clase B */ 28. paquete2.B objPaquete2 = new paquete2.B(); 29. /* Uso del nombre de la clase A sin su paquete */ 30. A objA = new A(); 31. }/* El metodo main termina aqui */ 32. }/* Definicion de la clase Principal termina aqui */

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 239

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

El código Java termina aquí

Se puede ver del programa anterior en la línea 3 de la clase Principal la sentencia import paquete1.A;, esto permite luego en la línea 9 usar el solo el nombre de la clase para acceder a ella. Por otro lado, a pesar de que no hay una sentencia import para la clase B del paquete paquete2, en la línea 10 se puede acceder a esta clase usando su nombre largo paquete2.B.

Fin del Ejemplo 7.3

A continuación se discute el empaquetado de paquetes que permite preservar la estructura de paquetes. El empaquetamiento de paquetes es útil durante el despliegue.

7. Agrupar Paquetes Las clases Java se almacenan en paquetes en aplicaciones de tiempo real, estos paquetes usan una estructura de árbol de directorios cuando son instalados. Es difícil almacenar y manejar esta estructura de árbol del directorio de árbol debido a los aspectos de almacenamiento y rendimiento a considerar. Por esto, la estructura de árbol de directorios se almacena dentro de un archivo plano que preserva la estructura del directorio. Los cargadores de clase, en el momento de cargar las clases empaquetadas, extraen la estructura de árbol del directorio desde el archivo plano.

El empaquetado (archives) es ventajoso porque permite reducir los tiempos de carga de las clases. Comprimen las clases y por tanto ocupan menos memoria; adicionalmente permite tener una unidad pequeña y sencilla para el despliegue (un único archivo de empaquetado).

El empaquetado que soporta la mayoría de los ambientes de desarrollo Java es el JAR. La mayoría de las características de los JAR son similares a las de los archivos TAR usados en UNIX. JAR comprime los datos usando un formato ZIP, que pueden ser visualizados usando WinZip.

El cargador de clases de Java sabe como buscar otros dos tipos de empaquetados archivos zip y cab. Pkzip, Winzip y otros programas crean archivos zip. Los archivos cab son creados con el utilitario de Microsoft MAKECAB. cab es un acrónimo para archivos cabinet, estos archivos se usan normalmente cuando se trabaja con la implementación Java de Microsoft, JView.

A continuación se discute cómo el paquete es desplegado.

8. Despliegue de Paquetes Un paquete puede ser desplegado como una única unidad. Se puede también empaquetar varios paquetes y desplegarlos juntos. Si un paquete tiene miembros interdependientes con otros paquetes, entonces éstos miembros interdependientes deben ser desplegados juntos.

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 240

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Si una aplicación la componen varios paquetes, la aplicación o el servidor de aplicaciones actuará como un objetivo para el despliegue. Los objetivos para el despliegue pueden referirse a cualquier directorio o empaquetado para localizar miembros de un paquete.

El cargador de clases de la aplicación especifica los miembros de paquetes a través de un classpath. Se puede especificar el classpath mediante una variable de ambiente (environment). Las Figuras 7.7 y 7.8 muestran como definir el classpath usando una variable de ambiente.

Figura 7.7: La Caja de Diálogo de Propiedades de Sistema en Windows 2000

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 241

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Figura 7.8: Definición del classpath Usando la Variable de Ambiente

Bajo ambiente Linux, se procede a crear la variable de ambiente de la siguiente forma:

• Edite el archivo ~/.bash_profile, donde ~ significa la ruta al directorio home del usuario. Ejemplo: /home/estudiante1

• En el archivo agregamos la siguiente línea.

export CLASSPATH=ruta1:ruta2

Donde ruta1 y ruta2, se sustituyen por las rutas específicas de los paquetes que se deseen incluir. Nótese que cada ruta esta separada por el carácter :

También se puede especificar el classpath usando las opciones –cp o –classpath, como sigue:

java –cp c:\ilscs01\lib com.ibm.ils.prueba.EjecutarExamen

Esto ejecutará el método main de la clase EjecutarExamen en el paquete com.ibm.ils.prueba. El cargador de la clase buscará el paquete en c:\ilscs01\lib.

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 242

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Existen varios tipos de despliegue que una aplicación Java puede usar. El tipo de despliegue puede ser un subárbol de directorio, un jar o un zip. Los archivos de clase (.class) pueden existir en el directorio, o como un archivo zip o como un archivo JAR. Las tres opciones se pueden usar en la misma aplicación Java y no necesitan estar en el mismo directorio, siempre que estén disponibles en el classpath.

Se ha introducido el término classpath. Se va a aprender qué son y qué hacen en la próxima sección.

8.1 ¿Qué es el classpath?

Un classpath almacena la ubicación particular que será usada por Java como la raíz de la jerarquía de paquetes. Aunque los paquetes resuelven problemas desde el punto de vista de control de acceso y conflictos de nombres, también crean dificultades al compilar y ejecutar programas.

Usualmente los programadores mantienen todas las clases en el paquete por defecto (sin nombre). Esto les permite compilar el código fuente y luego ejecutar el intérprete de Java usando el nombre de la clase en la línea de comandos. El paquete por defecto se hace corresponder con la carpeta física que está en el directorio actual de trabajo

Esto es factible debido a que el directorio actual de trabajo, por defecto (.), está usualmente en la variable de entorno classpath, que es definida por defecto por el sistema de tiempo de ejecución de Java. No sucede lo mismo con paquetes.

Asuma que un programador crea una clase llamada MiClase en el paquete miDirectorio. Idealmente, la estructura de directorios debe coincidir con el nombre del paquete. Por lo tanto, el programador crea un directorio llamado miDirectorio bajo el directorio actual, para guardar el archivo MiClase.java en él. Luego compila MiClase.java después de hacer a miDirectorio su directorio actual.

MiClase.class está ahora guardado en miDirectorio. Ahora, cuando se ejecuta MiClase, se muestra el siguiente mensaje de error:

Exception in thread "main" java.lang.NoClassDefFoundError: MiClase (wrong name: miDirectorio/MiClase).

Esto ocurre porque la clase ahora está almacenada en un paquete llamado miDirectorio, y ya no puede ser llamada simplemente MiClase.

En vez de eso, tiene que ser referida nombrando su jerarquía de paquetes, es decir, como miDirectorio.MiClase. Sin embargo, aún esto mostrará un mensaje de error:

Exception in thread "main" java.lang.NoClassDefFoundError: miDirectorio/MiClase.

La razón para esto estriba en la definición de la variable classpath del sistema del programador. El classpath, como se sabe, establece el tope de la jerarquía de clase.

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 243

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

En este caso, no existe un directorio llamado miDirectorio en el directorio actual de trabajo debido a que el directorio actual del programador es miDirectorio.

Ante esta coyuntura, el programador puede hacer una de dos cosas: ya sea añadir el tope de su jerarquía de clases de desarrollo a la variable classpath. Por ejemplo, si miDirectorio es un subdirectorio de C:\Java\Ejemplos, entonces C:\Java\Ejemplos se debe añadir a la variable classpath. El otro método es cambiar de directorio, subiendo un nivel, y luego usar java miDirectorio.MiClase o java miDirectorio/MiClase en la línea de comandos para ejecutar el programa. Esto le permite al programador usar java miDirectorio.MiClase sin importar el valor de la variable de ambiente.

Observe el Ejemplo 7.4.

Ejemplo 7.4

El siguiente programa ilustra los conceptos involucrados en torno al usar paquetes en Java.

El código Java comienza aquí...

1. package inversiones;

2.

3. /* Definicion de la clase Interes comienza aqui */

4. class Interes {

5. /* El metodo calcularInteres comienza aqui */

6. float calcularInteres(

7. float principio,

8. float anos,

9. float tarifa) {

10. 11. return (float) principio * anos * tarifa / 100; 12. }/* El metodo calcularInteres termina aqui */ 13. }/* Definicion de la clase Interes termina aqui */

14. package inversiones; 15. 16. /* Definicion de la clase Inversionista comienza aqui */ 17. public class Inversionista { 18. /* El metodo main comienza aqui */ 19. public static void main(String[] args) { 20. float p, a, t, si; 21. p = (float) (Math.random() * 100000);

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 244

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

22. a = (float) (Math.random() * 10); 23. t = (float) (Math.random() * 20); 24. 25. Interes in = new Interes(); 26. si = in.calcularInteres(p, a, t); 27. 28. System.out.println("Principio: " + p); 29. System.out.println("Numero de anos: " + a); 30. System.out.println("Tarifa de interes: " + t); 31. System.out.println("Interes simple: " + si); 32. }/* El metodo main termina aqui */ 33. }/* Definicion de la clase Inversionista termina aqui */

El código Java termina aquí

El programa anterior calcula el interés simple cuando se da el monto principal, el número de años de inversión y la tasa de interés. El método random() disponible en la clase Math del paquete java.lang se usa para generar números aleatorios. Se debe importar el paquete java.lang al inicio del programa para poder acceder a la clase Math disponible en el paquete. Sin embargo, el compilador de Java importa implícitamente el paquete java.lang en tiempo de compilación de cualquier programa Java. Por lo tanto, no se necesita importar el paquete java.lang para que el programa trabaje.

Ahora se compila y ejecuta el programa para ver cómo trabaja. Después de escribir el programa, se tiene que guardar en un directorio llamado inversiones, que es creado como un subdirectorio del directorio actual. Luego se puede compilar el programa de dos formas. Se puede compilar el programa desde el directorio inversiones como sigue:

javac Inversionista.java

Otra forma, es compilarlo desde un directorio un nivel superior al directorio investments como sigue:

javac inversiones/Inversionista.java

Después que el programa es compilado exitosamente, se debe ir un nivel superior del directorio inversiones para ejecutar el programa y dar el siguiente comando en la línea de comandos.

java inversiones/Inversionista

o

java inversiones.Inversionista

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 245

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

No se puede ejecutar el programa desde el mismo directorio inversiones. Se debe ir un nivel superior y luego ejecutar el programa. La compilación puede hacerse desde cualquier directorio. La salida del programa anterior puede ser como sigue (dependiendo de los números aleatorios que son generados):

Principio: 35830.254

Numero de anos: 3.349063

Tarifa de interes: 4.558226

Interes simple: 5469.77

Fin del Ejemplo 7.4

Ahora, observe algunos paquetes comúnmente usados en programas Java.

9. Paquetes Incorporados en Java Usados Comúnmente En esta sección se presenta una visión general de los paquetes que son ampliamente usados en Java.

9.1 java.awt

Se pueden usar las clases que están disponibles en el paquete java.awt para diseñar interfaces de usuario para aplicaciones, son también útiles cuando se usan gráficos e imágenes en las aplicaciones.

9.2 java.applet

Las clases disponibles en el paquete java.applet definen las características de los applets de Java y permite que se programen. Estas clases también permiten que un applet se comunique con su contexto de applet. El contexto del applet es la aplicación que carga y corre el applet. El marco de trabajo de applets comprende el applet y el contexto del applet.

9.3 java.beans

Los componentes Java beans son reutilizables y ampliamente usados en aplicaciones y applets Java. Para el desarrollo y ejecución de estos componentes reutilizables se deben usar las clases disponibles en el paquete java.beans.

9.4 java.io

Se puede obtener entrada del usuario del teclado usando flujos de entrada, adicionalmente se puede enviar la salida al monitor usando flujos de salida. Estos flujos también son útiles durante la serialización y la deserealización de objetos, así como cuando se lee de o se escribe a un archivo. Las clases en java.io definen los diferentes flujos de entrada y salida usados para las funciones descritas anteriormente.

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 246

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

9.5 java.lang

El paquete java.lang tiene las clases que proveen la funcionalidad básica de Java. Este paquete tiene la clase Object, que es la superclase de todas las otras clases en Java. Algunos métodos en esta clase proveen implementaciones estándares de algoritmos para equals(), hashCode(), y toString(). Este paquete también tiene la clase Math, que proporciona la implementación estándar para muchas funciones matemáticas útiles como: raíz cuadrada, exponente, seno, coseno, tangente, etc. Las clases String y StringBuffer de este paquete tienen varias operaciones que pueden realizarse sobre cadenas de caracteres.

Puede haber situaciones cuando los tipos de datos primitivos como integer, float, double, etc. se necesitan en la forma de objeto, para esto se tiene las clases envolventes (wrapper), que tienen un campo para almacenar el valor del tipo de dato primitivo.

Este paquete tiene la clase Throwable, que es la raíz de todas las clases de errores y excepciones. Este paquete tiene también muchas clases que permiten realizar operaciones de sistema, como aplicar las políticas de seguridad, crear procesos externos, etc.

9.6 java.util

Este paquete tiene esencialmente varias clases utilitarias que hacen el esfuerzo de la programación más simple; tiene clases que soportan el modelo de evento, que se usa en las interfaces de usuario de las aplicaciones. También tiene el marco de trabajo Collections, que permite manejar una colección (grupo) de objetos. Algunas de las clases utilitarias disponibles en el paquete java.util permiten generar números aleatorios, buscar la fecha y hora local de acuerdo a la región de la fecha y hora del sistema, etc. Provee la clase Vector que almacena una colección de referencias a objetos, puede variar en tamaño y contener objetos de diferentes tipos.

9.7 java.math

El paquete math en Java contiene clases que nos ayudan a trabajar con aritmética sobre números enteros y decimales de precisión arbitraria. Provee dos clases BigInteger para enteros y BigDecimal para números decimales.

9.8 java.text

Este paquete contiene clases para manipular texto, fechas, números y mensajes. Las clases están diseñadas para trabajar independientemente del lenguaje natural usado. Algunas de las clases provistas en este paquete son: Annotation, DateFormat, NumberFormat, MessageFormat, etc. También proporciona dos interfaces que realizan recorridos sobre datos textos.

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 247

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

9.9 java.net

Este paquete tiene varias clases que permiten construir aplicaciones en red. Usando las clases Socket y ServerSocket se pueden implementar un sistema cliente/servidor. Se pueden desarrollar aplicaciones para que un cliente se comunique con cualquier servidor disponible en la Internet. También, se pueden desarrollador aplicaciones para un servidor y host en la Internet. La clase URL y otras clases relacionadas permiten enviar datos a un URL así como recibir datos fácilmente.

9.10 java.rmi

La Invocación a Métodos Remota (Remote Method Invocation RMI) permite a un objeto ejecutándose en una JVM invocar a un método de otro objeto (objeto remoto) que se está ejecutando en una JVM diferente.

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 248

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Resumen Ahora que ha completado esta unidad, usted debe ser capaz de:

• Definir y crear un paquete. • Explicar cómo los paquetes se representan en el sistema de archivos. • Discutir acerca de protección de acceso en paquetes. • Describir los miembros del paquete. • Discutir cómo importar paquetes. • Explicar las variables classpath y describir su uso. • Explicar los paquetes incorporados más usados en Java.

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 249

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Unidad 7: Examen de Autoevaluación 1) Se pueden tener dos clases con el mismo nombre en dos paquetes diferentes en

Java. a) Verdadero b) Falso

2) Se puede usar el mismo nombre de paquete para diferentes definiciones de clases

en diferentes archivos. a) Verdadero b) Falso

3) ¿Cuáles de las siguientes sentencias son verdaderas acerca de la instrucción

package? a) Debe ser la primera instrucción declarada en un archivo fuente Java. b) Debe ir después de las instrucciones import. c) Se termina con un punto y coma. d) Asegura que todas las clases definidas en el archivo fuente pertenecen al

paquete.

4) Un programa Java tiene la siguiente instrucción: package p1.p2.p3.C;

¿Cuál de las siguientes es verdadera acerca de la instrucción?

a) C es el nombre del paquete, y el resto son simplemente nombres de directorios

b) C es el nombre de la clase, y p1.p2.p3 es el nombre del paquete c) p1.p2.p3.C es el nombre del paquete d) p1 es el nombre del directorio, y p2.p3.C es el nombre del paquete

5) Cuando no se especifica el paquete en un archivo fuente, la clase se almacena en

_____________. a) El paquete java.nombre b) Un paquete con el mismo nombre que el directorio actual c) El paquete por defecto (Default package) d) Ninguna de las anteriores

Core Java Guía del Estudiante

Unidad 7: Paquetes Libro 1: Core Java 250

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

6) Suponga que existe un programa llamado MiClase.java en un paquete llamado miPaquete, se puede ejecutar el programa desde el directorio miPaquete. a) Verdadero b) Falso

7) ¿Cuál de los siguientes paquetes es importado implícitamente por el compilador de

Java para cualquier programa Java? a) java.awt b) java.lang c) java.rmi d) java.net

8) ¿Para cuál de los siguientes será visible un miembro sin especificación de acceso

explícito en la definición de su clase? a) Subclases en otro paquete b) Clases en el mismo paquete c) Ambas

9) Si se tiene una clase sin ningún modificador para especificar su acceso, ¿cuál de

los siguientes niveles de acceso se asume que tiene? a) public b) protected c) package d) private

10) ¿Cuál de las siguientes instrucciones se pueden usar para crear un objeto de la clase Float que está en el paquete java.lang, sin importar el paquete java.lang? a) k=new lang.Float() b) Float f = new Float() c) Float f= new java.lang.Float() d) k= new java.lang.Float;

Guía del Estudiante Core Java

Libro 1: Core Java Unidad 7: Paquetes 251

© Copyright IBM Corp. 2007 Los materiales del curso no pueden ser reproducidos total o

parcialmente sin el previo permiso escrito de IBM.

Respuestas a la Unidad 7: Examen de Autoevaluación 1) a 2) a 3) a, c y d 4) b 5) c 6) b 7) b 8) b 9) c

10) b y c