Sie sind auf Seite 1von 71

Manual del Curso Java Básico

Manual del Curso Java Básico Programa de Tecnología en Cómputo UNIVERSIDAD NACIONAL AUTÓNOMA DE MÉXICO FACULTAD

Programa de Tecnología en Cómputo

del Curso Java Básico Programa de Tecnología en Cómputo UNIVERSIDAD NACIONAL AUTÓNOMA DE MÉXICO FACULTAD DE

UNIVERSIDAD NACIONAL AUTÓNOMA DE MÉXICO

FACULTAD DE INGENIERÍA

DIVISIÓN DE INGENIERÍA ELÉCTRICA

PROGRAMA DE TECNOLOGÍA EN CÓMPUTO

MANUAL DEL CURSO: JAVA BÁSICO

AUTORES:

CAMACHO PÉREZ HUGO CASTAÑEDA MUÑOZ RICARDO VARGAS MEJÍA ISAAC

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

TABLA DE CONTENIDO

1:Programación Orientada a Objetos

3

Introducción:

3

La Crisis del Software

3

La metodología orientada a objetos

4

Clases y objetos

4

Mensajes y métodos

5

5

Herencia

5

Polimorfismo

6

Abstracción

7

2:La Tecnología Java

8

La Plataforma Java

8

Tipos de programas en java

10

Compilación y Ejecución de Programas

10

Tipos de datos

12

El recolector de basura

13

3: Clases y objetos

14

Atributos y métodos

16

Constructores, la palabra reservada this

18

Variables y métodos de clase

25

Clases envolventes o wrappers

27

Arreglos

28

Arrays de dos dimensiones

30

Java archivos (JAR)

30

Limpieza: Finalización y recolección de

31

La condición de Muerto

34

Comentarios y documentación

35

Sintaxis

35

HTML empotrado

36

4:La Clase String

38

Comparación de Strings

39

5: Herencia

42

La palabra reservada super

43

Sobrecarga y sobreescritura de métodos

45

Sobrescritura de Métodos

46

Conversión hacia arriba (upcasting)

47

La palabra clave final

48

Para Datos

48

Constantes

50

Métodos Constantes

51

Clases Constantes

51

6: Polimorfismo

53

Clases y métodos abstractos

57

Interfaces y clases internas

59

Extender una interfaz con herencia

61

Clases Internas:

61

7:Paquetes

64

Apéndice A: Breve historia de Java

69

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

1:Programación Orientada a Objetos.

Introducción:

Los lenguajes de programación son técnicas que permiten expresar instrucciones que deben ser ejecutadas por la computadora. Este lenguaje de programación sirve de nexo entre la parte humana y la computadora.

Una de estas técnicas es la programación estructurada, en la cual se considera

a un dato como pasivo y existe para ser manipulado dentro del programa

durante el desarrollo del mismo. La variedad de sistemas hoy en día (y desde hace 20 años) ha demostrado que esta idea de estructuras de datos simples no es adecuada para soportar grandes cambios o cambios graduales.

Tales cambios surgieron cuando aumentaron las expectativas de lo que se podía hacer con un sistema informático, ocurrió entonces lo que se conoce como “crisis del software”, en la que no fue suficiente la mano de obra para mantener los sistemas actuales.

La Crisis del Software

La crisis del software es el hecho de que el software que se construye no solamente no satisface los requerimientos ni las necesidades pedidos por el cliente, sino que además excede los presupuestos y los horarios de tiempos. Como alternativas de esta crisis se plantearon varias propuestas:

La parametrización: Se trato de ubicar en datos externos al programa el conjunto de alternativas posibles para que durante la ejecución del proceso se determine que política utilizar para resolver un problema. Esta técnica no alcanzó a cubrir siquiera las necesidades inmediatas.

La Modularización: Se comenzó por la década de los 60’s, con Pascal, al definirse una nueva alternativa a la parametrización que estaba basada en encapsular comportamiento en módulos. El advenimiento de lenguajes como Modula II y Ada, en los 70’s, fueron muy promisorios para la construcción de sistemas de software “grande”.

El gran esfuerzo en la escritura de código como consecuencia del poco análisis

y diseño del sistema originó una nueva técnica llamada Metodología Orientada a Objetos.

En el paradigma de objetos, no es necesario el concepto de programa, pues cada objeto tiene una razón de ser para el ambiente que lo contiene y su comportamiento viene dado por su naturaleza.

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

La metodología orientada a objetos

A medida que se acercaban los años 80, la metodología orientada a objetos

comenzaba a madurar como un enfoque de desarrollo de software. Empezamos a crear diseños de aplicaciones de todo tipo utilizando la forma de

pensar orientada a los objetos e implementamos (codificamos) programas utilizando lenguajes y técnicas orientadas a los objetos.

La metodología orientada a objetos presenta características que lo hacen idóneo para el análisis, diseño y programación de sistemas; sin embargo, el análisis de requisitos, que es la relación entre la asignación de software al nivel del sistema y el diseño del software, se quedó atrás por lo que empezaron a surgir diferentes métodos de análisis y diseño orientado a objetos, entre los que destacan los métodos Booch, OOSE (Object Oriented Software Engineering) y OMT (Object Modeling Technique). Para poner fin a la "guerra de métodos" que se presentó en ese momento, se creó el Lenguaje Unificado de Modelado (UML).

La programación orientada a objetos, intenta simular el mundo real a traves del significado de objetos que contiene caracteristicas y funciones. Los lenguajes orientados a objetos se clasifican como lenguajes de quinta generacion.

Como su mismo nombre indica, la programación orientada a objetos se basa en la idea de un objeto, que es una combinacion de variables locales y procedimientos llamados metodos que juntos conforman una entidad de programación.

Clases y objetos

En la metodología orientada a objetos la esencia es el objeto. Un objeto en el mundo real viene a representar cualquier cosa: un plumón, una caja, una silla, un automóvil, etc. Por esta razón y en base a nuestra experiencia de la vida diaria podemos identificar grupos o clases de objetos, por ejemplo piense en 5 plumones como los que se muestran a continuación:

en 5 plumones como los que se muestran a continuación: De estos 5 plumones podemos dec

De estos 5 plumones podemos decir que pertenecen a la misma clase de objetos pero cada uno de ellos tiene las características necesarias que lo identifican como un objeto de la clase plumones y no con otros objetos como podría ser los objetos de tipo automóvil.

A partir de aquí podemos decir que un objeto tiene características propias que

llamaremos atributos y comportamientos o acciones propios de esa clase de

objetos que llamaremos métodos.

Manual del Curso Java Básico

Mensajes y métodos

Programa de Tecnología en Cómputo

Como ya hemos dicho un método es una acción que puede realizar un objeto. Cuando un objeto necesita interactuar con otro lo hace a través de un método.

inte ractuar con otro lo hace a través de un método. Figura 1.1 Cuando un objeto

Figura 1.1

Cuando un objeto A necesita que un objeto B ejecute alguno de sus métodos lo hace a través de sus métodos.

Un método se implementa dentro la clase que defina al objeto. Un buen diseño de clases hace que los atributos solo sean modificados mediante el acceso a un método.

Encapsulamiento.

Un objeto lo hemos representado de la siguiente manera:

Un objeto lo hemos represent ado de la siguiente manera: En donde se puede ver que

En donde se puede ver que loas datos (variables) y las acciones (métodos) se reúnen de tal forma que se oculte al mundo exterior parte de su información. De esta manera si queremos acceder a un atributo lo tenemos que hacer a través de alguno de sus métodos, a su vez los métodos también pueden ser restringidos de cierta forma.

Figura 1.2 El encapsulamiento provee una idea poderosa: la modularidad, es decir el código fuente puede ser escrito y darle mantenimiento de forma independiente al resto del programa y de los objetos que interactúan con él.

Herencia

La herencia es propiedad que permite a los objetos construirse a partir de otros objetos. El concepto de herencia está presente en nuestras vidas diarias donde las clases se dividen en subclases.

Hay diferentes tipos de herencia: los más importantes son simples y múltiples. La Herencia simple consiste en que una clase sólo puede heredar de otra clase llamada clase padre o superclase, en la herencia múltiple una clase puede heredar de una o mas clases.

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

del Curso Java Básico Programa de Tecnología en Cómputo Figura 1.3 La figura 1.3 muestra un

Figura 1.3

La figura 1.3 muestra un ejemplo de herencia simple, la clase B y la clase C son subclases de la clase A, que a su vez es la superclase de B y C, en esta figura la Clase C y la Clase B heredan de la Clase A.

Con la Herencia se obtienen múltiples beneficios, al heredar una clase de otra la se obtienen todos sus atributos y métodos que compone la clase padre. Con la herencia y con un buen diseño Orientado a Objetos podemos llevar a la práctica la reutilización de código, ya que si una clase es muy parecida a una anterior, podemos programar únicamente la diferencia entre estas y aplicar la herencia. La figura 1.4 muestra un ejemplo del uso de la herencia.

La figura 1.4 muestra un ejemplo del uso de la herencia. Polimorfismo Figura 1.4 El polimorfismo

Polimorfismo

Figura 1.4

El polimorfismo es otra característica esencial de los lenguajes de POO. Un objeto solo tiene una forma, la que se le asigna cuando es creado, pero la

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

referencia a ese objeto es polimorfita ya que puede referirse a objetos de diferentes clases. Para que esta referencia sea polimorfica debe haber necesariamente una relación de herencia entre las clases.

Por ejemplo, en nuestro diagrama de clases anterior:

Una referencia a objeto de la clase Empleado también puede ser una referencia a objeto de la clase Trabajador.

Una referencia a objeto de la clase Consultor también puede ser una referencia a objeto de la clase Trabajador.

Abstracción

Como mencionamos anteriormente en la POO para poder utilizar o crear un objeto es necesaria la clase del objeto, a esa clase de objeto la podemos definir como aquello que se desea abstraer, de esta forma el diseño de clases lo podemos considerar como una abstracción de datos, por ejemplo nuestro diagrama de clases de la figura 1.4 presenta una abstracción de datos en la parte superior y esta abstracción desminuye conforme se desciende del árbol, es decir, hablar de un trabajador resulta mas abstracto que hablar de un empleado o bien un consultor, conforme descendemos en el árbol las clases se convierten en algo mas concreto.

Diseñar una clase de una manera muy general para varias clases que hereden de ella nos proveerá de un mejor diseño como se verá mas adelante en este curso en el apartado de clases abstractas.

Manual del Curso Java Básico

2:La Tecnología Java.

Programa de Tecnología en Cómputo

El lenguaje de programación Java consiste en un lenguaje de programación y una plataforma. La mayoría de los lenguajes se caracterizan por ser interpretados (por ejemplo: Basic) o bien por ser compilados (por ejemplo C) esto determina la manera en que serán ejecutados por la computadora.

Java tiene la característica de ser al mismo tiempo compilado e interpretado. El compilador es el encargado de convertir el código fuente de un programa en un código intermedio llamado bytecode que es independiente de la plataforma en que se trabaje y que es ejecutado por el intérprete de Java que forma parte de

la Máquina Virtual de Java.

.
.

Figura 2.1

La Plataforma Java.

Una plataforma es el ambiente de hardware o software en el cual se ejecutan los programas. En general, la mayoría de las plataformas pueden ser descritas como una combinación de hardware y sistema operativo. Algunas de las plataformas más populares son Windows, Solaris, Linux y MacOS.

La plataforma Java difiere de las anteriores en que ésta es una plataforma basada únicamente en software que corre por encima de las plataformas

basadas

hardware.

en

La plataforma Java consta de dos componentes:

La Máquina Virtual de Java (JVM)

La Interfaz de Programación de Aplicaciones de Java (API Java)

A continuación se muestra una representación de los elementos que forman

parte de la plataforma Java.

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

del Curso Java Básico Programa de Tecnología en Cómputo Figura 2.2 La figura anterior muestra un

Figura 2.2

La figura anterior muestra un aspecto importante:

1.- Como puede verse la máquina virtual esta por encima de la plataforma del Hardware, esto quiere decir que la maquina virtual es la única que cambia de una plataforma a otra y es la encargada de interpretar y ejecutar los archivos Bytecode de nuestro programa.

La Interfaz de Programación de Aplicaciones (API) es el conjunto de paquetes y herramientas que nos ayudan a realizar la implementación de nuestro programa. Los programas de carácter general usan un API denominado J2SE (Java 2 Estándar Edición) y será el API que se use a lo largo de este manual.

La elección del API a utilizar depende del tipo de programa que queremos realizar, a continuación se muestran varios API (todos ellos bajo la tecnología Java) y una breve descripción de cada uno.

J2SE: Java Standard Edition. Se utiliza en la elaboración de programas standalone comúnmente utilizados para ser ejecutados de manera local en una PC.

J2EE: Java Enterprise Edition. Son programas para ser ejecutados en una arquitectura cliente – servidor.

J2ME: Java Micro Edition. Este API provee de las clases necesarias para la programación de dispositivos móviles tales como: Celulares, PDA’s, PALM, etc.

JavaCard: Con este API podemos incrustarnos en el mundo de la programación de las llamadas smartCards (como las tarjetas de telefono) a través del lenguaje java.

JNDI: Java Naming and Directory Interface. Nos permite enlazar programas Java con directorios de información como un directorio de información LDAP.

Existen numerosos API’s, los cuales podemos mezclar en su mayoría para lograr aplicaciones robustas y facilitar su implementación y mantenimiento.

Para obtener el J2SE que utilizaremos a lo largo del curso basta con entrar a la pagina de java: http://java.sun.com y descargarlo. Para detalles de la instalación revisar el apéndice C.

Manual del Curso Java Básico

Tipos de programas en java.

Programa de Tecnología en Cómputo

Los programas en Java suelen estar en una de las siguientes categorías:

Applets : Los applets son pequeños programas que se incorporan en una página Web y que por lo tanto, necesitan de un Navegador Web compatible con Java para poder ejecutarse. A menudo los applets se descargan junto con una página HTML desde un Servidor Web y se ejecutan en la máquina cliente.

Aplicaciones: Las aplicaciones son programas standalone de propósito general que normalmente se ejecutan desde la línea de comandos del sistema operativo. Con Java se puede realizar cualquier programa que normalmente se crearía con algún otro lenguaje de programación.

Servlets: Los servlets al contrario de los applets son programas que están pensados para trabajar en el lado del servidor y desarrollar aplicaciones Web que interactúen con los clientes. Los servlets son una alternativa de la programación CGI tradicional.

Compilación y Ejecución de Programas

La figura 2.3 muestra un esquema del proceso de construcción de una aplicación, para entender su funcionamiento pasaremos a ejecutar un ejemplo directamente.

pasaremos a ejecutar un ejemplo directamente. Figura 2.3 Nuestro primer programa consiste en el tr

Figura 2.3

Nuestro primer programa consiste en el tradicional hola mundo, escribirlo en un editor de texto plano como puede ser el block de notas de windows o bien el editor vi de unix.

Manual del Curso Java Básico

public class HolaMundo

{

public static void main(String arg[])

{

System.out.println("Mi primer programa en java");

}

}

Programa de Tecnología en Cómputo

Para ejecutar nuestro programa tenemos que seguir algunas reglas:

El nombre del archivo debe tener el nombre de la clase publica, en este caso el nombre del archivo corresponde a HolaMundo.java, Java es un lenguaje sensitivo lo cual quiere decir que hace una distinción entre mayúsculas y minúsculas, además la extensión siempre debe ser *.java.

Java sigue ciertas convenciones en la asignación de nombres a clases, métodos y variables, dicha convención se muestra a continuación y será la que adoptemos a lo largo de este manual:

Para nombrar clases se usa la letra en mayúscula al inicio de cada palabra, ejemplos:

o

NombreDeClase

o

HolaMundo

Para nombrar variables o atributos se usa la primer palabra en

minúsculas y en mayúscula la primer letra de las siguientes palabras que compongan el nombre, ejemplos:

o

miVariable

o

nombreDeVariable.

Para nombrar métodos se usa la misma convención que para nombrar variables, la diferencia es que los métodos van seguidos por paréntesis, ejemplos:

o

nombreDeMetodo()

o

realizarSuma()

De esta forma, podemos identificar clases, variables y métodos en el programa anterior:

HolaMundo: es clase String: es clase main(): método main de la clase. System: clase out: atributo de la clase System. println(): método del atributo out.

Hasta este momento tenemos listo el código fuente de nuestro programa en un archivo llamado HolaMundo.java este archivo esta listo para ser enviado al compilador de java: javac (de Java Compiler)

Para invocar al compilador abrir una ventana de comandos (inicio, ejecutar y escribir cmd en sistemas Windows 2000 y XP) e invocar al compilador de la siguiente manera:

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

C:\> javac HolaMundo.java

Si la compilación tuvo éxito el compilador nos devolverá el prompt del sistema operativo y nos generará un nuevo archivo en el directorio actual con el nombre: HolaMundo.class, que será el archivo byteCode.

Como siguiente paso hay que invocar a la maquina virtual de java (JVM) para que se encargue de interpretarlo, esto se hace mediante la siguiente instrucción:

C:\> java HolaMundo

Nótese la ausencia de la extensión del archivo en este comando, esto es por que Java busca la clase (el archivo ByteCode o .class) en las rutas especificadas por la variable de entorno CLASSPATH, de no existir la clase o no encontrarla java nos regresará un mensaje con el error encontrado.

La figura 2.4 muestra la ejecución del programa.

La figura 2.4 muestra la ejecución del programa. Figura 2.4 Tipos de datos primitivos. En el

Figura 2.4

Tipos de datos primitivos.

En el lenguaje de programación Java, a pesar de ser un lenguaje orientado a objetos, no todo es un objeto. Hay un grupo de tipos que tiene un tratamiento especial: se trata de los tipos “primitivos”, que se usaran frecuentemente en los programas. La razón para el tratamiento especial es que crear un objeto, para variables pequeñas y simples no es eficiente, para estos tipos Java vuelve al enfoque de C y C++. Es decir, en vez de crear un objeto, se crea una variable “automática” que no es una referencia. La variable guarda el valor, y se coloca en la pila para que sea más eficiente.

Java determina el tamaño de cada tipo primitivo. Estos tamaños no varían de una plataforma a otra como ocurre en la mayoría de los lenguajes.

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

Tipo primitivo

Tamaño

Mínimo

Máximo

Envoltura

bolean

-

-

-

Boolean

char

16

bits

Unicode 0

Unicote 2 16 -1

Character

byte

8 bits

-128

+127

Byte

short

16

bits

-2 15

+2 15 -1

Short

int

32

bits

-2 31

+2 31 -1

Integer

long

64

bits

-2 63

+2 63 -1

Long

float

32

bits

IEEE754

IEEE754

Float

double

64

bits

IEEE754

IEEE754

Double

void

-

-

-

Void

El estándar IEEE754 especifica básicamente lo siguiente:

Precisión sencilla: bit de signo + 8 bits de exponente + 23 bits de mantisa. Precisión doble: bit de signo +11 bits de exponente + 52 bits de mantisa.

Todos los tipos primitivos tienen asociada una envoltura o wrapper que se muestra en la última columna de la tabla anterior, esta envoltura será vista a detalle en el capitulo 3: clases envolventes.

El recolector de basura

Los programadores conocen la importancia de la inicialización, pero a menudo se les olvida la importancia de la limpieza. Java tiene un recolector de basura para recuperar la memoria de los objetos que ya no se usan, es decir de los cuales se ha perdido su referencia.

El recolector de basura se ejecuta en un proceso en segundo plano cada determinado tiempo, verifica que objetos han dejado de usarse y libera esa porción de memoria al sistema operativo para su nueva reasignación.

Sin embargo puede existir la necesidad de realizar alguna acción cuando un objeto es destruido, por ejemplo hacer uso de un destructor similar al de C++, Java soluciona este problema por medio del método finalize() que será visto en el siguiente capitulo.

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

3: Clases y objetos

Como hemos mencionado Java asume que se desea llevar a cabo exclusivamente programación orientada a objetos. Para poder crear un objeto es necesario que exista previamente la clase de ese objeto.

La definición de una clase especifica cómo serán los objetos de dicha clase, esto es, de que variables y de que métodos constarán.

La siguiente es la definición más simple de una clase:

class NombreClase

{

/* Declaración de la clase */

/* Aquí va la definición de variables y métodos */

}

Veamos un ejemplo, crearemos una clase llamada Alumno de esa clase vamos a crear un objeto. Ahora codificando esa clase, tenemos el siguiente código:

public class Alumno {

//Atributos de la clase String nombre; String apellidoPaterno; String apellidoMaterno; int edad; String carrera; int semestre; String numeroDeCuenta;

public static void main(String args[])

{

Alumno alumno1=new Alumno(); // creamos un nuevo objeto de tipo alumno.

alumno1.nombre="Juan";

alumno1.apellidoMaterno="Lopéz";

alumno1.apellidoPaterno="Hernandez";

alumno1.carrera="Computacion";

alumno1.edad=20;

alumno1.semestre=4;

alumno1.numeroDeCuenta="03021458";

System.out.println("Numero de cuenta: "+alumno1.numeroDeCuenta); System.out.println("Nombre: "+alumno1.nombre+" "+alumno1.apellidoPaterno+"

"+alumno1.apellidoMaterno);

System.out.println("Edad: "+alumno1.edad); System.out.println("Carrea: "+alumno1.carrera); System.out.println("Semestre: "+alumno1.semestre);

}

}

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

Veremos que es lo que esta pasando en este programa. En el método main de

la clase creamos un nuevo objeto de tipo Alumno en la sentencia:

Alumno alumno1=new Alumno();

Esta sentencia crea un nuevo objeto, con la palabra reservada new, y lo asigna

a la referencia alumno1. Una vez creado el objeto, este contiene una copia de todos los atributos declarados en la clase siempre y cuando no estén declarados como static. Cuando ya esta creado el objeto podemos acceder a un atributo mediante el operador punto (.). En el ejemplo también es interesante resaltar el uso de operador + para concatenar cadenas.

Al compilar y ejecutar este programa se obtendrá la siguiente salida:

Numero de cuenta: 03021458 Nombre: Juan Hernandez Lopéz Edad: 20 Carrea: Computacion Semestre: 4

Ahora vamos a crear otro objeto de la clase Alumno, este nuevo alumno tendrá como referencia: alumno2.

public class Alumno { // atributos de la clase String nombre; String apellidoPaterno; String apellidoMaterno; int edad; String carrera; int semestre; String numeroDeCuenta;

public static void main(String args[])

{

Alumno alumno1=new Alumno();// creamos un nuevo objeto de tipo alumno Alumno alumno2= new Alumno();// creamos otro nuevo objeto alumno1.nombre="Juan";//inicializamos sus atributos.

alumno1.apellidoMaterno="Lopéz";

alumno1.apellidoPaterno="Hernandez";

alumno1.carrera="Computacion";

alumno1.edad=20;

alumno1.semestre=4;

alumno1.numeroDeCuenta="03021458";

alumno2.nombre="Pedro";//inicializamos sus atributos.

alumno2.apellidoMaterno="Rodriguez";

alumno2.apellidoPaterno="Rodriguez";

alumno2.carrera="Ing. Electrica";

alumno2.edad=18;

alumno2.semestre=1;

alumno2.numeroDeCuenta="040012548";

System.out.println("Datos del alumno1:"); System.out.println("Numero de cuenta: "+alumno1.numeroDeCuenta);

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

System.out.println("Nombre: "+alumno1.nombre+" "+alumno1.apellidoPaterno+"

"+alumno1.apellidoMaterno);

System.out.println("Edad: "+alumno1.edad); System.out.println("Carrea: "+alumno1.carrera); System.out.println("Semestre: "+alumno1.semestre); System.out.println("\nDatos del alumno2:"); System.out.println("Numero de cuenta: "+alumno2.numeroDeCuenta); System.out.println("Nombre: "+alumno2.nombre+" "+alumno2.apellidoPaterno+"

"+alumno2.apellidoMaterno);

System.out.println("Edad: "+alumno2.edad); System.out.println("Carrea: "+alumno2.carrera); System.out.println("Semestre: "+alumno2.semestre);

}

}

En este ejemplo hemos creado el nuevo objeto el cual tiene la referencia alumno2. de esta forma podemos darnos cuenta de que cada objeto, tanto alumno1 como alumno2, contiene una copia de los atributos de la clase los cuales almacenan valores de forma independiente.

La salida de este programa es la siguiente:

Datos del alumno1:

Numero de cuenta: 03021458 Nombre: Juan Hernandez Lopéz Edad: 20 Carrea: Computacion Semestre: 4

Datos del alumno2:

Numero de cuenta: 040012548 Nombre: Pedro Rodriguez Rodriguez Edad: 18 Carrea: Ing. Electrica Semestre: 1

Atributos y métodos

En la versión 2 de nuestra clase Alumno hemos creado 2 objetos de esta clase, sin embargo el código propuesto hasta el momento resulta un tanto ineficiente ya que si quisiéramos crear 40 alumnos de un salón de clase e imprimir sus datos repetiríamos bastante el código que hasta ahorita tenemos y esto va en contra de la POO en donde la reutilización de código es algo primordial.

Si observamos las líneas de código en donde se imprimen los datos de cada alumno encontraremos que son prácticamente las mismas, entonces ¿Podemos unir esas líneas en una sola que permitan imprimir los datos de cualquier objeto tipo Alumno creado?. La respuesta es sí y esto se hará a través de un método.

Como ya se dijo en el capitulo 1, un método es una acción que puede ejecutar un objeto, en este caso la acción ha realizar será imprimir el valor de sus

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

atributos. La implementación del método, para imprimir el valor de los atributos, se muestra en la siguiente versión de la clase Alumno que renombraremos como Alumno2 para notar de mejor manera la evolución de nuestra clase.

public class Alumno2 { // atributos de la clase String nombre; String apellidoPaterno; String apellidoMaterno; int edad; String carrera; int semestre; String numeroDeCuenta;

public void imprimirDatos()

{

System.out.println("Numero de cuenta: "+numeroDeCuenta); System.out.println("Nombre: "+nombre+" "+apellidoPaterno+" "+apellidoMaterno); System.out.println("Edad: "+edad); System.out.println("Carrea: "+carrera); System.out.println("Semestre: "+semestre);

}

public static void main(String args[])

{

 

Alumno2 alumno1=new Alumno2();// creamos un nuevo objeto de tipo alumno Alumno2 alumno2= new Alumno2();// creamos otro nuevo objeto alumno1.nombre="Juan";//inicializamos sus atributos.

alumno1.apellidoMaterno="Lopéz";

alumno1.apellidoPaterno="Hernandez";

alumno1.carrera="Computacion";

alumno1.edad=20;

alumno1.semestre=4;

alumno1.numeroDeCuenta="03021458";

alumno2.nombre="Pedro";//inicializamos sus atributos.

alumno2.apellidoMaterno="Rodriguez";

alumno2.apellidoPaterno="Rodriguez";

alumno2.carrera="Ing. Electrica";

alumno2.edad=18;

alumno2.semestre=1;

alumno2.numeroDeCuenta="040012548";

alumno1.imprimirDatos();

alumno2.imprimirDatos();

}

}

Hemos agregado el método imprimirDatos, este método es llamado por los dos objetos creados en las instrucciones:

alumno1.imprimirDatos();

alumno2.imprimirDatos();

Cada objeto ejecuta este método el cual, al ser ejecutado por alumno1, imprime el valor de los atributos de este objeto, es decir de alumno1, cuando es llamado

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

por alumno2 el método imprimirDatos busca el valor de los atributos de ese objeto, es decir del que lo mando llamar.

Constructores, la palabra reservada this

En nuestra clase Alumno2 revisemos las siguientes líneas:

Alumno2 alumno1=new Alumno2();// creamos un nuevo objeto de tipo alumno Alumno2 alumno2= new Alumno2();// creamos otro nuevo objeto alumno1.nombre="Juan";//inicializamos sus atributos.

alumno1.apellidoMaterno="Lopéz";

alumno1.apellidoPaterno="Hernandez";

alumno1.carrera="Computacion";

alumno1.edad=20;

alumno1.semestre=4;

alumno1.numeroDeCuenta="03021458";

alumno2.nombre="Pedro";//inicializamos sus atributos.

alumno2.apellidoMaterno="Rodriguez";

alumno2.apellidoPaterno="Rodriguez";

alumno2.carrera="Ing. Electrica";

alumno2.edad=18;

alumno2.semestre=1;

alumno2.numeroDeCuenta="040012548";

Podemos notar que la inicialización de los atributos de cada objeto vuelve a ser prácticamente la misma, ¿Podemos unir estas líneas en un método como se hizo con el método de imprimirDatos?. La respuesta de nueva cuenta es sí.

Cuando se crea un objeto se manda llamar un método que recibe el nombre de constructor. Los constructores son métodos especiales que se ejecutan cuando un objeto es creado, su principal función es inicializar los atributos de un objeto y cuentan con las siguientes características:

Son llamados una sola vez cuando es creado el objeto.

Tiene el mismo nombre de la clase.

No regresa ningún valor de retorno.

Hasta este momento no hemos definido ningún constructor para nuestra clase Alumno, pero sin embargo hemos estado haciendo uso del constructor por default. El constructor por default es agregado automáticamente por Java siempre y cuando la clase no contenga ningún constructor. Otra característica del constructor por default es que es un constructor que no tiene argumentos. En la siguiente línea estamos utilizando el constructor por default.

Alumno2 alumno1=new Alumno2(); Alumno2 alumno2= new Alumno2();

La sentencia new Alumno2() constituye la llamada al constructor por default. Ahora agregaremos un constructor a nuestra clase Alumno2 que ahora la renombraremos por Alumno3.

Manual del Curso Java Básico

public class Alumno3 { // atributos de la clase String nombre; String apellidoPaterno; String apellidoMaterno; int edad; String carrera; int semestre; String numeroDeCuenta;

Programa de Tecnología en Cómputo

public Alumno3()

{

System.out.println("Creando un nuevo Alumno

");

}

public void imprimirDatos()

{

System.out.println("Numero de cuenta: "+numeroDeCuenta); System.out.println("Nombre: "+nombre+" "+apellidoPaterno+" "+apellidoMaterno); System.out.println("Edad: "+edad); System.out.println("Carrea: "+carrera); System.out.println("Semestre: "+semestre);

}

public static void main(String args[])

{

 

Alumno3 alumno1=new Alumno3();// creamos un nuevo objeto de tipo alumno Alumno3 alumno2= new Alumno3();// creamos otro nuevo objeto alumno1.nombre="Juan";//inicializamos sus atributos.

alumno1.apellidoMaterno="Lopéz";

alumno1.apellidoPaterno="Hernandez";

alumno1.carrera="Computacion";

alumno1.edad=20;

alumno1.semestre=4;

alumno1.numeroDeCuenta="03021458";

alumno2.nombre="Pedro";//inicializamos sus atributos.

alumno2.apellidoMaterno="Rodriguez";

alumno2.apellidoPaterno="Rodriguez";

alumno2.carrera="Ing. Electrica";

alumno2.edad=18;

alumno2.semestre=1;

alumno2.numeroDeCuenta="040012548";

alumno1.imprimirDatos();

alumno2.imprimirDatos();

}

}

En este ejemplo hemos sobrescrito el constructor por default, esta nueva implementación solo imprime un mensaje cuando el constructor es invocado, la salida del programa quedará de la siguiente forma:

Creando un nuevo Alumno Creando un nuevo Alumno Numero de cuenta: 03021458

Manual del Curso Java Básico

Nombre: Juan Hernandez Lopéz Edad: 20 Carrea: Computacion Semestre: 4 Numero de cuenta: 040012548 Nombre: Pedro Rodriguez Rodriguez Edad: 18 Carrea: Ing. Electrica Semestre: 1

Programa de Tecnología en Cómputo

Lo que demuestra que el constructor es invocado cada vez que se crea un nuevo objeto de la clase. Ahora adecuaremos la firma del constructor para que pueda recibir argumentos e inicialice los atributos del objeto, para esta cambiaremos a firma del constructor de la siguiente manera:

public Alumno3(String nom, String apePat, String apeMat, int anios, String car, int sem, String cuenta)

{

}

Observa que hemos cambiado intencionalmente el nombre de las variables para que no concidan con el nombre de los atributos, es seguida explicaremos la razón. Con esta modificación al constructor nuestro programa quedará de la siguiente manera:

public class Alumno4 { // atributos de la clase String nombre; String apellidoPaterno; String apellidoMaterno; int edad; String carrera; int semestre; String numeroDeCuenta;

public Alumno4(String nom, String apePat, String apeMat, int anios, String car, int sem, String cuenta)

{

 

System.out.println("Creando un nuevo Alumno nombre=nom; apellidoPaterno=apePat; apellidoMaterno=apeMat; edad=anios; carrera=car; semestre=sem; numeroDeCuenta=cuenta;

");

}

public void imprimirDatos()

{

System.out.println("Numero de cuenta: "+numeroDeCuenta); System.out.println("Nombre: "+nombre+" "+apellidoPaterno+" "+apellidoMaterno); System.out.println("Edad: "+edad); System.out.println("Carrea: "+carrera); System.out.println("Semestre: "+semestre);

}

Manual del Curso Java Básico

public static void main(String args[])

{

//creamos un nuevo objeto de tipo alumno Alumno4 alumno1=new

Programa de Tecnología en Cómputo

Alumno4("Juan","Lopez","Hernadez",20,"computacion",4,"03021458");

//creamos otro nuevo objeto Alumno4 alumno2= new Alumno4("Pedro","Rodriguez","Rodriguez",18,"Ing.

Electrica",1,"040012548");

alumno1.imprimirDatos();

alumno2.imprimirDatos();

}

}

Al correr este código veremos que se obtiene el mismo resultado. Ahora revisemos de nueva cuenta el constructor, cambiemos en nombre de las variables de los argumentos del constructor por el mismo nombre que tienen los atributos, el resultado podría ser inesperado, el código se encuentra en el archivo Alumno5.java en el cual se hizo el siguiente cambio en el constructor.

public Alumno4(String nombre, String apellidoPaterno, String apellidoMaterno, int edad, String carrera, int semestre, String numeroDeCuenta)

{

 

System.out.println("Creando un nuevo Alumno nombre=nombre; apellidoPaterno=apellidoPaterno; apellidoMaterno=apellidoMaterno; edad=edad; carrera=carrera; semestre=semestre; numeroDeCuenta=numeroDeCuenta;

");

}

El resultado de realizar estos cambios se muestra a continuación:

Creando un nuevo Alumno Creando un nuevo Alumno Numero de cuenta: null Nombre: null null null Edad: 0 Carrea: null Semestre: 0 Numero de cuenta: null Nombre: null null null Edad: 0 Carrea: null Semestre: 0

Como puede verse los atributos de cada objeto no fueron inicializados, esto ocurre debido a que la asignación de variables en el constructor es únicamente de forma local, es decir la sentencia:

nombre=nombre;

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

La variable nombre del lado derecho hace referencia a la variable nombre declarada en los argumentos del constructor siendo la misma variable la del lado derecho, es decir es una asignación entre la misma variable, nunca se afecta al atributo del objeto. Para poder hacer una distinción de una variable local y un atributo del objeto con el mismo nombre se usa la palabra reservada this.

Con el uso de la palabra reservada this, podemos mejorar nuestro código de la siguiente manera:

public class Alumno6 { // atributos de la clase String nombre; String apellidoPaterno; String apellidoMaterno; int edad; String carrera; int semestre; String numeroDeCuenta;

public Alumno6(String nombre, String apellidoPaterno, String apellidoMaterno, int edad, String carrera, int semestre, String numeroDeCuenta)

{

 

System.out.println("Creando un nuevo Alumno this.nombre=nombre; this.apellidoPaterno=apellidoPaterno; this.apellidoMaterno=apellidoMaterno; this.edad=edad; this.carrera=carrera; this.semestre=semestre; this.numeroDeCuenta=numeroDeCuenta;

");

}

public void imprimirDatos()

{

System.out.println("Numero de cuenta: "+numeroDeCuenta); System.out.println("Nombre: "+nombre+" "+apellidoPaterno+" "+apellidoMaterno); System.out.println("Edad: "+edad); System.out.println("Carrea: "+carrera); System.out.println("Semestre: "+semestre);

}

public static void main(String args[])

{

//creamos un nuevo objeto de tipo alumno Alumno6 alumno1=new

Alumno6("Juan","Lopez","Hernadez",20,"computacion",4,"03021458");

//creamos otro nuevo objeto Alumno6 alumno2= new Alumno6("Pedro","Rodriguez","Rodriguez",18,"Ing.

Electrica",1,"040012548");

alumno1.imprimirDatos();

alumno2.imprimirDatos();

}

}

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

En este ejemplo, que produce la misma salida de las versiones anteriores de Alumno, podemos decir que la palabra reservada this hace referencia al objeto que mando llamar el método, en esta caso el constructor.

Invocando a Constructores desde Constructores.

Cuando se escriben varios constructores para una clase, hay veces en las que uno quisiera invocar a un constructor desde otro para evitar la duplicación de código. Esto se puede lograr utilizando la palabra reservada this.

La palabra clave this toma un significado diferente cuando se le da una lista de parámetros: hace una llamada explícita al constructor que coincida con la lista de parámetros. Por consiguiente, hay una manera directa de llamar otros constructores. Ejemplo:

public class Flor { int numeroPetalos=0; String texto=null;

public Flor(int petalos)

{

numeroPetalos=petalos; System.out.println("Constructor: Parametro entero solo, petalos= "+petalos);

}

public Flor(String ss)

{

System.out.println("Constructor: Parametro cadena solo, texto= "+ss); texto=ss;

}

public Flor(String ss, int petalos)

{

this(petalos); //! this(ss); //No se pueden invocar dos this.texto=ss; System.out.println("Constructor: Parametro cadena y entero");

}

public Flor()

{

this("Hola",20);

System.out.println("Constructor por defecto (Sin parametros)");

}

public void print()

{

//this(11); // No se puede invocar this dentro de un no-constructor System.out.println("Numero de petalos: "+numeroPetalos+" texto= "+texto);

}

public static void main(String args[])

{

Flor x= new Flor(); x.print(); Flor y= new Flor("Rosa",18); y.print();

}

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

}

En el ejemplo anterior podemos observar el uso de varios constructores para crear objetos. Además el uso de this con parámetros, es decir como llamada al constructor, debe ser la primer cosa que se haga o se obtendrá un mensaje de error del compilador. La salida del programa anterior es la siguiente:

Constructor: Parametro entero solo, petalos= 20 Constructor: Parametro cadena y entero Constructor por defecto (Sin parametros) Numero de petalos: 20 texto= Hola Constructor: Parametro entero solo, petalos= 18 Constructor: Parametro cadena y entero Numero de petalos: 18 texto= Rosa

Para terminar con este apartado mostraremos un ejemplo final de la clase Alumno hasta ahora modificada pero esta vez en archivos distintos, es decir por un lado en un archivo la clase Alumno que renombraremos por Alumno7 y por el otro una clase llamada escuela en un archivo distinto. Estos dos archivos deberán encontrarse en el mismo directorio por el momento.

//Alumno7.java

public class Alumno7 { // atributos de la clase String nombre; String apellidoPaterno; String apellidoMaterno; int edad; String carrera; int semestre; String numeroDeCuenta;

public Alumno7(String nombre, String apellidoPaterno, String apellidoMaterno, int edad, String carrera, int semestre, String numeroDeCuenta)

{

 

System.out.println("Creando un nuevo Alumno this.nombre=nombre; this.apellidoPaterno=apellidoPaterno; this.apellidoMaterno=apellidoMaterno; this.edad=edad; this.carrera=carrera; this.semestre=semestre; this.numeroDeCuenta=numeroDeCuenta;

");

}

public void imprimirDatos()

{

System.out.println("Numero de cuenta: "+numeroDeCuenta); System.out.println("Nombre: "+nombre+" "+apellidoPaterno+" "+apellidoMaterno); System.out.println("Edad: "+edad); System.out.println("Carrea: "+carrera); System.out.println("Semestre: "+semestre);

}

}

Manual del Curso Java Básico

//Escuela.java public class Escuela {

public static void main(String args[])

{

//creamos un nuevo objeto de tipo alumno Alumno7 alumno1=new

Programa de Tecnología en Cómputo

Alumno7("Juan","Lopez","Hernadez",20,"computacion",4,"03021458");

//creamos otro nuevo objeto Alumno7 alumno2= new Alumno7("Pedro","Rodriguez","Rodriguez",18,"Ing.

Electrica",1,"040012548");

alumno1.imprimirDatos();

alumno2.imprimirDatos();

}

}

Se comprobará que la salida no cambia en relación a programas anteriores.

Variables y métodos de clase

Generalmente, al crear una clase se está describiendo qué apariencia tienen sus objetos y cómo se comportan. No se tiene nada hasta crear un objeto de ese clase con new, momento en el que se crea el espacio de almacenamiento y los métodos pasan a estar disponibles.

Pero hay dos situaciones en las que este enfoque no es suficiente. Una es cuando se desea tener solamente un fragmento de espacio de almacenamiento para una parte concreta de datos, independientemente de cuántos objetos se creen, o incluso aunque no se cree ninguno. La otra es si se necesita un método que no esté asociado con ningún objeto particular de esa clase. Es decir, se necesita un método al que se puede invocar incluso si no se ha creado ningún objeto. Ambos efectos se pueden lograr con la palabra clave static. Al decir que algo es estático se está indicando que el dato o método no está atado a ninguna instancia de objeto de esa clase. Con los datos y métodos ordinarios no estáticos, es necesario crear un objeto para poder utilizarlos, estos métodos y datos que necesitan un objeto para poder ser utilizados reciben el nombre de variables y métodos de instancia.

Para declarar un dato o un método static, basta con colocar la palabra clave static antes de la definición, por ejemplo:

public class PruebaEstatica

{

static int i=47;

}

Ahora, incluso si se construyen dos objetos de tipo PruebaEstatica, sólo habrá un espacio de almacenamiento, es decir ambos objetos compartirán la misma i. La sintaxis recomendada de llamar a una variable o método de clase es la siguiente:

Manual del Curso Java Básico

NombreDeClase.nombreDeAtributo;

NombreDeClase.nombreDeMétodo();

Programa de Tecnología en Cómputo

Modifiquemos nuestro ejemplo de la clase Alumno para ver un ejemplo:

//Alumno8.java

public class Alumno8 { // atributos de la clase String nombre; // variable de instancia, cada que creas un objeto se crea un copia para cada objeto String apellidoPaterno; String apellidoMaterno; int edad; String carrera; int semestre; String numeroDeCuenta; static int numeroDeAlumnos=0;// variable de clase, no se crean copias para cada objeto, es fija.

public Alumno8(String nombre, String apellidoPaterno, String apellidoMaterno, int edad, String carrera, int semestre, String numeroDeCuenta)

{

 

System.out.println("Creando un nuevo Alumno

");

this.nombre=nombre; this.apellidoPaterno=apellidoPaterno; this.apellidoMaterno=apellidoMaterno; this.edad=edad; this.carrera=carrera; this.semestre=semestre; this.numeroDeCuenta=numeroDeCuenta; numeroDeAlumnos++;// modificamos una variable de clase

}

public static String metodoDeClase()

{

String mensaje="Metodo de clase"; //nombre="Paco"; //Un método de clase o puede modificar variables de instancia return mensaje;

}

public void imprimirDatos()

{

System.out.println("Numero de cuenta: "+numeroDeCuenta); System.out.println("Nombre: "+nombre+" "+apellidoPaterno+" "+apellidoMaterno); System.out.println("Edad: "+edad); System.out.println("Carrea: "+carrera); System.out.println("Semestre: "+semestre);

}

}

Hemos agregado un método y una variable estática, ahora modifiquemos el archivo Escuela para mandar llamar las variables estáticas.

//Escuela2.java

public class Escuela2 {

public static void main(String args[])

Manual del Curso Java Básico

{

Programa de Tecnología en Cómputo

//Las variables y métodos de clase se pueden usar sin crear un objeto System.out.println("Numero total de Alumnos: "+Alumno8.numeroDeAlumnos); System.out.println("Mensaje del metodo de clase:

"+Alumno8.metodoDeClase());

//creamos un nuevo objeto de tipo alumno Alumno8 alumno1=new

Alumno8("Juan","Lopez","Hernadez",20,"computacion",4,"03021458");

//creamos otro nuevo objeto Alumno8 alumno2= new Alumno8("Pedro","Rodriguez","Rodriguez",18,"Ing.

Electrica",1,"040012548");

//Despues de crear dos objetos, la variable estatica se ha modificado System.out.println("Numero total de Alumnos: "+Alumno8.numeroDeAlumnos); //Los objetos tambien pueden accesar a las variables y metodos estaticos System.out.println("Desde alumno1, Numero de Alumnos:

"+alumno1.numeroDeAlumnos);

//Los objetos tambien pueden modificar las variables estaticas directamente:

alumno2.numeroDeAlumnos++;

System.out.println("Numero total de Alumnos: "+Alumno8.numeroDeAlumnos);

}

}

La salida de este programa deberá ser la siguiente:

Numero total de Alumnos: 0 Mensaje del metodo de clase: Metodo de clase Creando un nuevo Alumno Creando un nuevo Alumno Numero total de Alumnos: 2 Desde alumno1, Numero de Alumnos: 2 Numero total de Alumnos: 3

Clases envolventes o wrappers

Los tipos de datos primitivos tienen asociado una clase “envoltura”. Esto quiere decir que si se desea hacer un objeto no primitivo para representar ese tipo primitivo, se hace uso del envoltorio asociado. Por ejemplo:

char c= ‘x’; Charácter C = new Character(c)

Veamos un ejemplo más práctico, queremos realizar un programa que reciba desde la línea de comandos dos números y que los sume, mostrando el resultado en pantalla. Para utilizar los parámetros de la línea de comandos utilizamos el arreglo de String que viene en la firma del método main.

public static void main(String args[])

La referencia args es un arreglo de objetos tipo String, que veremos más adelante en este capitulo, para acceder al primer parámetro utilizaremos el índice 0 del arreglo y 1 para el segundo. Pero esto ocasionará un problema: los datos estarán en un objeto String lo que dificultara la operación de suma que queremos realizar, para solucionar esto utilizaremos la clase envolvente Integer

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

que nos provee de un método para realizar esta conversión de un String a un int. El siguiente ejemplo ilustra lo anterior.

public class SumaDeNumeros {

public static void main(String args[])

{

int a= Integer.parseInt(args[0]); int b= Integer.parseInt(args[1]); int c= a+b; System.out.println("El resultado de la suma es: "+c);

}

}

para ejecutar este programa hay que hacerlo de la siguiente manera:

C:\ javac SumaDeNumeros.java C:\ java SumaDeNumeros 1 2

Arreglos.

Hasta ahora, hemos descrito datos (variables) individuales y aislados. Por

ejemplo:

int contador, suma; String nombre;

Estos datos trabajan por su cuenta, desempeñando funciones útiles en los programas, como contadores, sumas o lo que sea. Podemos pensar en estas variables como posiciones en memoria que tienen asignados nombres individuales.

En contraste, en la vida tratamos con datos que no están aislados, sino agrupados en una colección de información. Para solucionar este problema contamos con un tipo de almacenamiento que son los arrays. Existen muchas otras formas de guardar objetos, pero como se verá a continuación el array tiene dos aspectos especiales con respecto a otros tipos de contenedores: la eficiencia y el tipo.

El array es la forma más eficiente que proporciona Java para almacenar y acceder al azar a una secuencia de objetos (verdaderamente, referencias a

objetos). El array es una secuencia lineal simple, que hace rápidos los accesos

a elementos, pero se paga por esa velocidad: cuando se crea un objeto array su tamaño es limitado y no puede variarse.

Para declara un array basta escribir:

int[] suma;

o bien:

Manual del Curso Java Básico

int suma[]:

Programa de Tecnología en Cómputo

Son exactamente la misma sentencia, que declara que la referencia suma será un array de objetos.

Un ejemplo de un primer array de cadenas es el siguiente:

public class PrimerArray{ public static void main(String arg[]){ String nombres[] ={ "Juan", "Maria", "Antonio", "Victoria"

};

nombres[2]="Alejandro";

System.out.println("Numero de elementos en el array: "+nombres.length);

System.out.println(nombres[0]);

System.out.println(nombres[1]);

System.out.println(nombres[2]);

System.out.println(nombres[3]);

}

}

Java permite varias formas de inicializar los array, el acceso a cada elemento de un array se realiza mediante el índice del elemento. He aquí la salida del programa:

Numero de elementos en el array: 4 Juan Maria Alejandro Victoria

También podemos realizar array de tipos primitivos, la diferencia es que el objeto array no guarda referencias como array con objetos, si no que guarda directamente el valor de cada elemento. Ejemplo:

public class ArrayDeEnteros {

}

public static void main(String[] args) {

int[] enteros; enteros = new int[10];

// inicializa los elementos del arreglo y lo imprime for (int i = 0; i < enteros.length; i++) { enteros[i] = i;

// declara un arreglo de enteros // crea el objeto que alamcenara 10 enteros

System.out.print(enteros[i] + " ");

}

}

Este ejemplo muestra otra forma de inicializar el array, primero se declara el tamaño y luego se inicializa el array cabe destacar que para especificar el

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

tamaño del array se usa new int[10], nótese el cambio de corchetes por los tradicionales paréntesis, la salida del programa se muestra a continuación:

0 1 2 3 4 5 6 7 8 9

Arrays de dos dimensiones

Java ofrece una extensión natural de los arreglos unidimensionales a dos dimensiones, para crear un arreglo de dos dimensiones usamos dobles corchetes, por ejemplo:

int[][] ventas = new ventas[4][7] ;

Esta instrucción declara una matriz de 4 x 7 elementos.

Java archivos (JAR)

El formato ZIP también se usa en el formato de archivos JAR (Java ARchive), que es una forma de coleccionar un grupo de archivos en un único archivo comprimido, exactamente igual que el ZIP. Sin embargo, como todo lo demás en Java, los ficheros JAR son multiplataforma, por lo que no hay que preocuparse por aspectos de plataforma. También se pueden incluir archivos de audio e imagen, o archivos de clases.

Un archivo JAR consta de un único archivo que contiene una colección de archivos ZIP junto con una declaración que los describe.

La utilidad jar que viene con el JDK de Sun comprime automáticamente los archivos que se seleccionan. Se invoca en la línea de comandos:

jar [opciones] destino [manifiesto] archivo(s)Entrada

Las opciones son simplemente una colección de letras, los usuarios de linux notarán una semejanza con las opciones tar. Las opciones son:

c

Crea un archivo nuevo vacío.

t

Lista la tabla de contenidos.

x

Extrae todos los archivos.

x file

Extraer el archivo nombrado.

f

Nombre del archivo.

m

Indica que el primer parámetro será el archivo de declaración.

v

Genera una salida que describe que va haciendo jar.

O

Simplemente almacena los archivos; no los comprime (usarlo para crear un archivo JAR que se puede poner en el CLASSPATH)

M

No crear automáticamente un archivo de declaración.

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

He aquí una forma habitual de invocar a Jar:

C:\jar cf miArchivoJar.jar *.class

Esto crea un fichero JAR llamado miFichero.jar que contiene todos los archivos de clase del directorio actual, junto con un archive declaración creado automáticamente.

El archivo de declaración que es creado automáticamente puede tener varias utilidades como por ejemplo indicar la clase a partir de la cual se podrá ejecutar el archivo completo JAR. Por ejemplo vamos a comprimir en un archivo JAR las dos ultimas clases que trabajamos de la versión de nuestra clase Alumno que son: Alumno8 y Escuela2. Primero vamos a crear nuestro archivo Manifiesto que tenga la siguiente información, este archivo puede ser escrito en un editor de texto plano como puede ser notepad de Windows o vi de Linux:

Manifest-Version: 1.0 Created-By: 1.5.0_02 (Sun Microsystems Inc.) Main-Class: Escuela2

Nota que hemos especificado la clase que contiene el método main a ejecutar, guarda este archivo en el mismo directorio de tus clases con el nombre:

MANIFEST.MF

Como siguiente paso vamos a comprimir los archivos, en la línea de comandos escribe:

C:\ >jar cmf MANIFEST.MF Escuela.jar Alumno8.class Escuela2.class

Para ejecutar el archivo escribir:

C:\>java –jar Escuela.jar

Limpieza: Finalización y recolección de basura.

En el capitulo anterior hablamos del recolector de basura como un proceso que se ejecuta en segundo plano y libera la memoria de aquellos objetos que han perdido su referencia. Considere ahora un caso muy inusual. Supóngase que los objetos asignan memoria “especial” sin utilizar new. El recolector de basura sólo sabe liberar la memoria asignada por new, por lo que ahora no sabrá como liberar esa memoria “especial” del objeto. Para hacer frente a este caso, Java proporciona un método denominado finalize( ) que se puede definir en cada clase. He aquí como se supone que funciona. Cuando el recolector de basura está preparado para liberar el espacio de almacenamiento utilizado por el objeto, primero invocara a finalize( ), y sólo recuperará la memoria del objeto durante la pasada del recolector de basura. Por tanto, si se elige usar finalize(), éste te proporciona la habilidad de llevar acabo alguna limpieza importante a la vez que la recolección de basura.

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

Hay que señalar que no es lo mismo que un destructor para C++, que es una función que siempre se invoca. Java no cuenta con algo parecido así que si se necesita para un programa en específico tendrá que ser programado por su cuenta. Por ejemplo, considere un objeto que dibuja una figura en pantalla, el recolector de basura puede eliminar el objeto pero no la información que dibujo en pantalla.

Pero la limpieza y recolección de basura esta ligada exclusivamente a la liberación de memoria. Resulta que la necesidad de finalize( ) se limita a casos especiales, en los que un objeto puede reservar espacio de almacenamiento de forma distinta a la creación de un objeto.

Esto puede ocurrir principalmente a través de métodos nativos, que son la forma de invocar a código no-Java desde Java.

Una de las cosas para las que puede ser útil finalize( ) es para observar el proceso de recolección de basura. El ejemplo siguiente resume las descripciones anteriores del recolector de basura:

//Silla.java //Demostracion de recolector de Basura y //finalizacion public class Silla {

static boolean recolector=false; static boolean f= false; static int creadas = 0; static int finalizadas =0; int i; public Silla()

{

i= ++creadas;

if(creadas==47)

System.out.println("Creadas 47");

}

public void finalize()

 

{

 

if(!recolector) {//la primera vez que se invoca a finalize():

recolector=true; System.out.println("Comenzando a finalizar tras haber creado "+ creadas +"sillas");

}

if(i==47)

{

System.out.println("Finalizando la silla #47, "+ "Poniendo el indicador que evita la creacion de mas

sillas");

 

f=true;

}

finalizadas++; if(finalizadas>=creadas) System.out.println("Las "+finalizadas+" han sido finalizadas");

 

}

Manual del Curso Java Básico

}

//Basura.java public class Basura { public static void main(String args[])

{

//Mientras no se haya puesto la bandera, //hacer sillas y cadenas de texto while(!Silla.f)

{

new Silla(); new String("Ocupar Espacio");

Programa de Tecnología en Cómputo

}

System.out.println("Despues de haber creado todas las sillas: \n"+ "Creadas en total: "+Silla.creadas+", total finalizadas:

"+Silla.finalizadas);

}

}

El programa anterior crea muchos objetos Silla, y en cierto momento después de que el recolector de basura comience a ejecutarse el programa deja de crear objetos Silla. Dado que el recolector puede ejecutarse en cualquier momento, uno no sabe exactamente cuando empezará, y hay un indicador denominado recolector para indicar si el recolector a comenzado su ejecución o no. Un segundo indicador f es la forma de que Silla le comunique al bucle main( ) que deberá dejar de hacer objetos. Ambos indicadores se ponen dentro de finalize( ), que se invoca durante la recolección de basura.

La creación de un objeto String en cada iteración es simplemente la asignación de almacenamiento extra para animar al recolector de basura a actuar, lo que hará cuando se empiece a poner nervioso por la cantidad de memoria disponible.

Una posible salida del programa anterior se muestra a continuación:

Creadas 47 Comenzando a finalizar tras haber creado 12207sillas Finalizando la silla #47, Poniendo el indicador que evita la creacion de mas sillas Las 33864 han sido finalizadas Despues de haber creado todas las sillas:

Creadas en total: 33865, total finalizadas: 33864

Por consiguiente, no se invoca a todos los finalizadotes cuando acaba el programa. Recuerde que ni el recolector de basura ni la finalización están garantizadas. Si la Máquina Virtual Java (JVM) no está a punto de quedarse sin memoria, entonces (sabiamente) no malgastará tiempo en recuperar memoria mediante el recolector de basura.

Existe también una forma de invocar al recolector de basura explícitamente cuando el programador lo desee y esto se hace mediante el método:

System.gc(). Si se llama a System.gc() se finalizan todos los objetos, por consiguiente se destruirán todos los objetos que no estén en uso en ese momento.

Manual del Curso Java Básico

La condición de Muerto

Programa de Tecnología en Cómputo

En el momento que uno deja de estar interesado en un objeto –cuando está listo para ser eliminado– el objeto debería estar en cierto estado en el que su memoria puede ser liberada de manera segura. Por ejemplo, si el objeto representa un fichero abierto, ese fichero debería ser cerrado por el programador antes de que el objeto sea eliminado por el recolector de basura. Si no se eliminan correctamente ciertas porciones de objeto, se tendrá un fallo en el programa que podría ser difícil de encontrar. El valor de finalize( ) es que puede usarse para descubrir esta condición, incluso si no se invoca siempre. Si una de las finalizaciones acaba revelando el fallo, se descubre el problema, que es lo que verdaderamente hay que cuidar.

He aquí un ejemplo simple de cómo debería usarse:

//Libro.java

//Utilizacion de finalize() para detectar un objeto // que no ha sido correctamente eliminado public class Libro { boolean comprobado=false; public Libro(boolean comprobar)

{

comprobado=comprobar;

}

void correcto()

{

comprobado=false;

}

public void finalize()

{

if(comprobado) System.out.println("Error: comprobado");

}

}

//CondicionDeMuerto.java public class CondicionDeMuerto {

public static void main(String[] args)

{

Libro novela = new Libro(true); //Eliminacion Correcta novela.correcto(); //Cargarse la referencia olvidando la limpieza new Libro(true); //forzar la recoleccion de basura y finalizacion System.gc();

}

}

La condición de muerto consiste en que todos los objetos libros supuestamente serán comprobados antes de ser recogidos por el recolector de basura, pero en el método main( ) un error del programador no comprueba alguno de los libros.

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

Sin finalize( ) para verificar la condición de muerte, este error sería difícil de encontrar.

Comentarios y documentación

Hay dos tipos de comentarios en Java. El primero es el estilo de comentarios tradicional de C, que fue heredado por C++. Estos comentarios empiezan por /* y pueden extenderse a lo largo de varias líneas hasta encontrar */.

Una de las partes más interesantes del lenguaje Java es que los diseñadores no sólo tuvieron en cuenta que la escritura de código era la única actividad importante, sino que también pensaron en la documentación del código. Esto se hizo mediante comentarios especiales que se incrustan dentro del código fuente, sin embargo, es necesaria una sintaxis especial y una herramienta para extraer esos comentarios.

La herramienta para extraer comentarios se le denomina javadoc. Utiliza parte de la tecnología del compilador Java para extraer etiquetas de comentarios especiales. La salida de javadoc es un archivo HTML que puede visualizarse a través del navegador web. Gracias a javadoc se tiene incluso un estándar para la creación de documentación, tan sencillo que se puede incluso esperar o solicitar documentación con todas las bibliotecas Java.

Sintaxis

Todos los comandos de javadoc se dan únicamente en comentarios /**. Estos comentarios acaban con */. Hay dos formas principales de usar javadoc:

empotrar HTML, o utilizar “etiquetas doc”. Kas etiquetas doc son comandos que comienzan por ‘@’ y se sitúan al principio de una línea de comentarios.

Hay tres “tipos” de documentación en forma de comentarios, que corresponden con el elemento al que precede el comentario: una clase, una variable o un método. Es decir, el comentario relativo a una clase aparece justo antes de la definición de la misma; el comentario relativo a una variable precede siempre a la definición de la variable, y un comentario de un método aparece inmediatamente antes de la definición de un método. Un ejemplo simple:

/** Un comentario de clase */ public class PruebaDoc

{

 

/** Un comentario de una variable */ public int i;

/** Un comentario de un método public void f( ){}

*/

}

Manual del Curso Java Básico

HTML empotrado

Programa de Tecnología en Cómputo

Javadoc pasa comandos HTML al documento HTML generado. Esto permite un uso total de HTML; sin embargo, el motivo principal es permitir dar formato al código, como:

/**

* <pre>

* System.out.println(new Date());

* </pre> */

También puede usarse HTML como se haría en cualquier otro documento web para dar formato al propio texto de las descripciones:

/**

*

Uno puede <em>incluso</em> insertar una lista:

*

<ol>

*

<li> Elemento uno

*

<li> Elemento dos

*

<li> Elemento tres

*

</ol>

*/

@see: Referencias a otras clases. Los tres tipos de comentarios de documentación (de clase, variable y métodos) pueden contener etiquetas @see, que permiten hacer referencia a la documentación de otras clases. Javadoc generará HTML con las etiquetas @see en forma de vínculos a la otra documentación. La forma es:

@see NombreDeClase

@version: Información de la versión de la clase. La forma es:

@version información-de-version.

@author: Suele ser el nombre del creador pero podría ser cualquier cosa como la dirección de correo. La forma de uso es:

@author información-del-autor

@param: permite especificar una descripción de un parámetro. Forma de uso:

@param nombre-parámetro descripción

@return: especifica una descripción para un valor de retorno

@return descripción

@throws: Descripción para las excepciones, que serán vistas en el curso de java Avanzado.

Manual del Curso Java Básico

@throws nombre-de-clase descripción

Ejemplo de documentación.

import java.util.Vector; /**

Programa de Tecnología en Cómputo

*

Este es un ejemplo de código comentado<br>

*

<h1>Se pueden usar etiquetas de HTML</h1>,

*

para darle formato al texto.<br>

*

En esta parte, se describe sobre las características, uso, y funcionamiento

*

de la clase en general.

*

@author PROTECO

*

*/ public class Comentada extends Vector implements Runnable{

/**

* Asi se comentan los atributos

*/ protected String atributo; /**

* Este es una atributo de clase, y no modificable

*/ static final int VALOR=10; /**

*

Tambien los métodos constructores pueden ir comentados

*

*/ public Comentada(){

}

/**

* Asi se comentan lo métodos. Se da una descripción de lo que hacen

* y se pueden dar algunos ejemplos. Se utilizan

* @param arg1

* @param arg2

* @param num

* @return

* @throws Exception

Comentario del parámetro 1

Comentario del parámetro 2

Comentario del parámetro n

Comentario del valor de retorno

Comentario sobre alguna excepción que regrese

*/ private int Metodo(String arg1,Vector arg2,int num) throws Exception{ return 0;

}

public void run(){

}

/**

* @param args

*/ public static void main(String[] args) {

// TODO Auto-generated method stub

}

}

Para ejecutar el comando javadoc en un ventana de comandos escribir:

javadoc Comantada.java

y la herramienta javadoc generará el archivo html en el directorio actual.

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

4:La Clase String

Dentro de un objeto de la clases String o StringBuffer, Java crea un array de caracteres de una forma similar a como lo hace el lenguaje C++. A este array se accede a través de métodos de la clase. Los String se pueden crear explícitamente o implícitamente. Para crear un String implícitamente basta poner una cadena de caracteres entre comillas dobles. Por ejemplo, cuando se escribe:

System.out.println("El primer programa");

Java crea un objeto de la clase String automáticamente. Para crear un String explícitamente escribimos:

String str=new String("El primer programa");

También se puede escribir, alternativamente

String str="El primer programa";

Para crear un String nulo se puede hacer de estas dos formas

String str=""; String str=new String();

Un string nulo es aquél que no contiene caracteres, pero es un objeto de la clase String. Sin embargo,

String str;

Está declarando un objeto str de la clase String, pero aún no se ha creado ningún objeto de esta clase.

Cómo se obtiene información acerca del String

Una vez creado un objeto de la clase String podemos obtener información relevante acerca del objeto a través de las funciones miembro. Para obtener la longitud, número de caracteres que guarda un String se llama al método length.

String str="El primer programa"; int longitud=str.length();

Podemos conocer si un string comienza con un determinado prefijo, llamando al método startsWith, que devuelve true o false, según que el string comience o no por dicho prefijo:

String str="El primer programa"; boolean resultado=str.startsWith("El");

En este ejemplo la variable resultado tomará el valor true.

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

De modo similar, podemos saber si un String finaliza con un conjunto dado de caracteres, mediante el método endsWith:

String str="El primer programa"; boolean resultado=str.endsWith("programa");

Si se quiere obtener la posición de la primera ocurrencia de la letra p, se usa la

función indexOf:

String str="El primer programa"; int pos=str.indexOf('p');

Para obtener las sucesivas posiciones de la letra p, se llama a otra versión de la misma función

pos=str.indexOf('p', pos+1);

El segundo argumento le dice a la función indexOf que empiece a buscar la primera ocurrencia de la letra p a partir de la posición pos+1. Otra versión de indexOf busca la primera ocurrencia de un substring dentro del String:

String str="El primer programa"; int pos=str.indexOf("pro");

Vemos que una clase puede definir varios métodos con el mismo nombre pero que tienen distinto número de parámetros o de distinto tipo, esto se conoce como sobrecarga de métodos y será visto a detalle en el siguiente capitulo.

Comparación de Strings

La comparación de strings nos da la oportunidad de distinguir entre el operador lógico == y la función miembro equals de la clase String. En el siguiente código:

public class ClaseString { public static void main(String[] args)

{

String str1="El lenguaje Java";

String str2=new String("El lenguaje Java");

if(str1==str2)

{

System.out.println("Los mismos objetos");

}

else

{

System.out.println("Distintos objetos");

}

if(str1.equals(str2))

{

System.out.println("El mismo contenido");

}

else

{

System.out.println("Distinto contenido");

Manual del Curso Java Básico

}

}

}

Programa de Tecnología en Cómputo

Esta porción de código devolverá que str1 y str2 son distintos objetos pero con el mismo contenido. str1 y str2 ocupan posiciones distintas en memoria pero guardan los mismos datos. Cambiemos la segunda sentencia y escribamos:

String str1="El lenguaje Java"; String str2=str1; System.out.prinln("Son el mimso objeto "+(str1==str2);

Los objetos str1 y str2 guardan la misma referencia al objeto de la clase String creado. La expresión (str1==str2) devolverá true. Así cuando deseamos comparar el contenido de dos String se debe usar el método equals, ya que de otra forma, con el operador = = compararemos si los Objetos apuntan a la misma dirección de memoria.

El método comapareTo devuelve un entero menor que cero si el objeto String es menor (en orden alfabético) que el String dado, cero si son iguales, y mayor que cero si el objeto String es mayor que el String dado.

String str="Tomás"; int resultado=str.compareTo("Alberto");

La variable entera resultado tomará un valor mayor que cero, ya que Tomás está después de Alberto en orden alfabético.

String str="Alberto"; int resultado=str.compareTo("Tomás");

La variable entera resultado tomará un valor menor que cero, ya que Alberto está antes que Tomás en orden alfabético.

Extraer un substring de un String

En muchas ocasiones es necesario extraer una porción o subcadena de un String dado. Para este propósito hay un método de la clase String denominada substring. Para extraer un substring desde una posición determinada hasta el final del String escribimos:

String str="El lenguaje Java"; String subStr=str.substring(12);

Se obtendrá el substring "Java". Una segunda versión del método substring, nos permite extraer un substring especificando la posición de comienzo y la el final.

String str="El lenguaje Java"; String subStr=str.substring(3, 11);

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

Se obtendrá el substring "lenguaje". Recuérdese, que las posiciones se empiezan a contar desde el indice cero.

Convertir un número a String Para convertir un número en String se emplea el método estático valueOf:

int valor=10; String str=String.valueOf(valor);

La clase String proporciona versiones de valueOf para convertir los datos primitivos: int, long, float, double.

Cuando introducimos caracteres en un control de edición a veces es inevitable que aparezcan espacios ya sea al comienzo o al final. Para eliminar estos espacios tenemos el método trim:

String str=" 12 "; String str1=str.trim();

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

5: Herencia

La herencia es una parte integral de Java. Resulta que siempre se esta haciendo herencia cuando se crea una clase, pero a menos que se herede explícitamente de otra clase, se hereda implícitamente de la clase raíz estándar de Java Object.

Cuando se hereda, se dice: “Esta clase nueva es como esa clase vieja”. Se dice esto en el código dando el nombre de la clase pero antes de abrir el cuerpo de clase, se pone la palabra reservada extends seguida del nombre de la clase base. Cuando se hace esto, automáticamente se tiene todos los atributos y métodos de la clase base. He aquí un ejemplo.

//Animal.java public class Animal {

String raza; String nombre; int edad; String tamaño; String tipoDePelaje;

public Animal(){ System.out.println("El animal es totalmente Rebelde");

}

public Animal(String nombre, String nombre){ this.nombre=nombre; this.raza= nombre;

}

public void comer() { System.out.println("Alimentando al animal");

}

public void respirar() { System.out.println("El animal respira");

}

public void reproduccion() { System.out.println("El animal puede reproducirse");

}

public void dormir() { System.out.println("El animal duerme");

}

}

//Gato.java public class Gato extends Animal { int numVidas=7; String tipoDeComida; public void maullar() { System.out.println("El gato esta maullando");

Manual del Curso Java Básico

}

public void rasgar() { System.out.println("El gato esta rasgando");

}

public Gato(String nombre,String raza) {

this.nombre=nombre; this.raza=raza; System.out.println("\nGato creado");

}

public static void main(String args[])

{

 

Gato gato1=new Gato("Batman","Angora");

gato1.respirar();

gato1.maullar();

gato1.rasgar();

gato1.dormir();

}

}

Programa de Tecnología en Cómputo

En la clase Gato muestra el uso de la herencia en este ejemplo, como puede verse la clase Gato no incorpora explícitamente los atributos nombre y raza, estos son heredados directamente por la clase Animal. Como dijimos en el capitulo uno, también los métodos son heredados, esto se puede ver en las llamadas a los métodos respirar y dormir. He aquí la salida del programa:

El animal es totalmente Rebelde

Gato creado El animal respira El gato esta maullando El gato esta rasgando El animal duerme

Hace falta aun notar un punto importante en este programa, al observar la salida del programa anterior nos encontramos en la primera linea: “El animal es totalmente Rebelde”, Esta línea muestra que en la herencia se crean los objetos correspondientes que se encuentran el la cima del árbol jerárquico, en este caso antes de haber creado un Gato fue necesario crear primero un objeto de tipo Animal, se invoca al constructor por default de la clase animal, debido a que la clase gato no invoca de manera explicita ningún constructor. Invocar explícitamente a un constructor es posible mediante el uso de la palabra reservada super.

La palabra reservada super

Como ya dijimos, una vez creado un objeto de tipo Gato se creará, en primera instancia, un objeto tipo Animal, el programa anterior crea este objeto por medio del constructor por default, pero ¿Por qué no crear el objeto Animal llamando otro constructor? Si usamos el segundo constructor de animal podemos inicializar las variables nombre y raza de manera automática, para

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

invocar a un constructor en específico debemos hacer uso de la palabra super. Modificando el programa anterior tenemos:

//Animal.java public class Animal2 {

String raza; String nombre; int edad; String tamaño; String tipoDePelaje;

public Animal2(){ System.out.println("El animal es totalmente Rebelde");

}

public Animal2(String nombre, String raza){ this.nombre=nombre; this.raza= nombre; System.out.println("En el constructor llamado por super");

}

public void comer() { System.out.println("Alimentando al animal");

}

public void respirar() { System.out.println("El animal respira");

}

public void reproduccion() { System.out.println("El animal puede reproducirse");

}

public void dormir() { System.out.println("El animal duerme");

}

}

public class Gato2 extends Animal2 { int numVidas=7; String tipoDeComida; public void maullar() { System.out.println("El gato esta maullando");

}

public void rasgar() { System.out.println("El gato esta rasgando");

}

public Gato2(String nombre,String raza) { super(nombre, raza); System.out.println("\nGato creado");

}

public static void main(String args[])

{

Manual del Curso Java Básico

Gato2 gato1=new Gato2("Batman","Angora");

gato1.respirar();

gato1.maullar();

gato1.rasgar();

gato1.dormir();

}

}

Programa de Tecnología en Cómputo

Hemos agregado la llamada al constructor por medio de super en método constructor de Gato, cabe señalar que super buscará un constructor que contenga ese tipo de parámetros, de no existir, la compilación no tendrá éxito. Cuando se usa super de esta manera debe ser la primera instrucción en aparecen en el constructor. La salida del programa se muestra a continuación:

En el constructor llamado por super

Gato creado El animal respira El gato esta maullando El gato esta rasgando El animal duerme

Sobrecarga y sobreescritura de métodos

La firma de un método es la combinación del tipo de dato que regresa, su nombre y su lista de argumentos.

La sobrecarga de métodos es la creación de varios métodos con el mismo nombre pero con diferentes firmas y definiciones. Java utiliza el número y tipo de argumentos para seleccionar cuál definición de método ejecutar.

Java diferencia los métodos sobrecargados con base en el número y tipo de argumentos que tiene el método y no por el tipo que devuelve.

También existe la sobrecarga de constructores: Cuando en una clase existen constructores múltiples, se dice que hay sobrecarga de constructores. La sobrecarga de constructores ya la hemos manejado en algunos ejemplos de este manual, a continuación se muestra un ejemplo que ilustra la sobrecarga de constructores.

//SobreCarga.java public class SobreCarga{ public SobreCarga(){ System.out.println("Soy un objeto creado por el constructor sin argumentos");

}

public SobreCarga(int num){ System.out.println("Soy un objeto creado por el constructor con un argumento

int= "+num);

}

public SobreCarga(String cad){

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

System.out.println("Soy un objeto creado por el constructor con un argumento

String= "+cad);

}

public SobreCarga(char c,int num,String cad){ System.out.println("Soy un objeto creado por el constructor con tres

argumentos char= "+c+" ,int= "+num+" ,String= "+cad);

}

public static void main(String[] args){ new SobreCarga(2); new SobreCarga("Hola enfermera"); new SobreCarga();

new SobreCarga('Z',7,"No hay papel"); new SobreCarga(9);

}

}

Sobrescritura de Métodos.

Una subclase hereda todos los métodos de su superclase que son accesibles a dicha subclase a menos que la subclase sobrescriba los métodos.

Una subclase sobrescribe un método de su superclase cuando define un método con las mismas características (nombre, número y tipo de argumentos) que el método de la superclase.

Las subclases emplean la sobre-escritura de métodos la mayoría de las veces para agregar o modificar la funcionalidad del método heredado de la clase padre. Como ejemplo, regresemos al ejemplo de la clase Animal y Gato. Esta vez la Clase Gato sobrescribirá el método dormir de la clase Animal cuyo código no variara con respecto a la última versión, es decir Animal2.

//Gato3.java

public class Gato3 extends Animal2 { int numVidas=7; String tipoDeComida; public void maullar() { System.out.println("El gato esta maullando");

}

public void rasgar() { System.out.println("El gato esta rasgando");

}

public Gato3(String nombre,String raza) { super(nombre, raza); System.out.println("\nGato creado");

}

public void dormir()

{

System.out.println("El gato esta durmiendo, no molestar");

}

public static void main(String args[])

{

Gato3 gato1=new Gato3("Batman","Angora");

gato1.respirar();

Manual del Curso Java Básico

}

gato1.maullar();

gato1.rasgar();

gato1.dormir();

}

He aquí la Salida:

En el constructor llamado por super

Gato creado El animal respira El gato esta maullando El gato esta rasgando El gato esta durmiendo, no molestar

Programa de Tecnología en Cómputo

Observe que la última línea ha cambiado por la sobre-escritura del método dormir. Ahora modifiquemos la clase Gato, esta vez agregaremos la siguiente línea:

super.dormir();

Justo antes de la línea que imprime: “El gato esta durmiendo, no molestar”. Es decir:

public void dormir()

{

super.dormir(); System.out.println("El gato esta durmiendo, no molestar");

}

Esta es otra forma de usar super, en la cual se ejecuta un método de la clase Padre o superclase. Al usar super de esta manera, no hay ninguna restricción del lugar donde se haga la llamada al método.

Conversión hacia arriba (upcasting)

Hasta ahora, podemos pensar que el aspecto más importante acerca de la herencia, es que podemos heredar métodos a nuestra clase hija. Sin embargo, la herencia es importante por la relación que se crea entre la clase padre y la clase hija.

Veamos un ejemplo, consideremos como clase base Instrumento que representa instrumentos musicales, y una clase derivada Viento. Como sabemos, la herencia implica que todos los métodos de la clase padre estarán disponibles en la clase hija; entonces; cualquier mensaje que le enviemos a la clase padre podrá ser enviado a la clase hija.

//Instrumento.java //Herencia y upcasting public class Instrumento{

Manual del Curso Java Básico

public void play(){} public static void tune(Instrumento i){ //… i.play();

}

}

//Viento.java //Los instrumentos de Viento son instrumentos! //porque tienen la misma interfaz public class Viento extends Instrumento{ public static void main(String[] args){ Viento flauta=new Viento(); Instrumento.tune(flauta); //Upcasting

}

}

Programa de Tecnología en Cómputo

Vemos en el ejemplo lo siguiente: el método tune() tiene como argumento un objeto Instrumento. Sin embargo, en el método Viento.main() el método tune() es llamado con una referencia de tipo Viento. Como podemos comprobar, los objetos de tipo Viento también son objetos de tipo Instrumento.

Vemos que el upcasting tiene sentido ya que partimos de una clase más específica a una más general, por lo que se cumple la regla. La clase hija podrá tener más métodos que la clase padre, sin embargo, debe contener por lo menos los métodos de la clase padre.

La palabra clave final

La palabra clave final de Java tiene significados ligeramente diferentes dependiendo del contexto, pero en general dice: “Esto no puede cambiarse”. Se podría querer evitar cambios por dos razones: diseño o eficiencia. Dado que estas dos razones son bastantes diferentes, es posible utilizar erróneamente la palabra clave final.

Para Datos

Una variable o atributo puede ser una constante que deseamos no cambia nunca en nuestro programa, esto se puede realizar anteponiendo la palabra final a la declaración de una variable. Utilizar constantes declaradas por final puede eliminar parte de la sobrecarga en tiempo de ejecución de un programa.

Al usar final con referencias a objetos en vez que con datos primitivos, su significado se vuelve algo confuso. Con un dato primitivo, final convierte el valor en constante, pero con una referencia a un objeto, final hace de la referencia una constante. Una vez que la referencia se inicializa a un objeto, ésta nunca se puede cambiar para que apunte a otro objeto. Sin embargo se puede modificar el objeto en sí; Java no proporciona ninguna manera de convertir un objeto arbitrario en una constante.

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

He aquí un ejemplo que muestra el funcionamiento de los campos final:

//Valor.java public class Valor { int i = 1;

}

//DatosConstantes.java public class DatosConstantes { //Pueden ser constantes en tiempo de compilacion final int variable1 = 9; static final int VAL_DOS=99; //Tipica constante publica public static final int VAL_TRES=39; //No pueden ser constantes en tiempo de compilacion final int variable4= (int)(Math.random()*20); static final int variable5=(int)(Math.random()*20);

Valor v1= new Valor(); final Valor v2 = new Valor(); static final Valor v3 = new Valor(); //Arrays:

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

public void escribir(String id)

{

System.out.println(id+" : variable4 ="+variable4+ ", variable5 ="+variable5);

}

public static void main(String[] args)

{

DatosConstantes fd1= new DatosConstantes(); //! fd1.variable1++; //Error: No se puede cambiar el valor fd1.v2.i++; //El objeto no es constante fd1.v1= new Valor(); //OK, el Objeto no es final for(int i=0;i< fd1.a.length;i++)

fd1.a[i]++;

//! fd1.v2 = new Valor(); // No se puede //! fd1.v3 = new valor3(); //Cambiar la referencia //! fd1.a= new int[3];

fd1.escribir("fd1");

System.out.println("Creando un nuevo DatosConstantes"); DatosConstantes fd2= new DatosConstantes();

fd1.escribir("fd1");

fd2.escribir("fd2");

}

}

Nota que los datos primitivos static final, se escriben en mayúsculas por convención. Una posible salida del programa se muestra a continuación:

fd1 : variable4 =12, variable5 =14 Creando un nuevo DatosConstantes fd1 : variable4 =12, variable5 =14

Manual del Curso Java Básico

fd2 : variable4 =19, variable5 =14

Programa de Tecnología en Cómputo

Fíjese que los valores de variable4 para fd1 y fd2 son únicos, pero el valor variable5 no ha cambiado al crear el segundo objeto DatosConstantes. Esto es porque es estático y se inicializa una vez en el momento de la carga y no cada vez que se crea un nuevo objeto.

Las variables v2 y v3 demuestran el significado de una referencia final. Como se puede ver en main( ), justo porque v2 sea final, no significa que no pueda cambiar su valor. Sin embargo, no se puede reubicar v2 a un nuevo objeto, precisamente por que es final. Esto es lo que final significa para un referencia.

Constantes Blancas.

Java permite la creación de constantes blancas, que son campos declarados como final pero a los que no se da un valor de inicialización. En cualquier caso, se debe inicializar una constante blanca antes de utilizarla, y esto lo asegura el propio compilador. Sin embargo, las constantes blancas proporcionan mucha mayor flexibilidad en el uso de la palabra clave final puesto que, por ejemplo, un campo final incluido en una clase puede ahora ser diferente para cada objeto, y sin embargo, sigue reteniendo su cualidad de inmutable. He aquí un ejemplo:

//ConstanteBlanca.java public class ConstanteBlanca {

final int i=0; //Constante inializada final int j; // Constante blanca final Elemento p; //Referencia a constante blanca

//Las constantes blancas DEBEN inicializarse en el constructor

public ConstanteBlanca(){ j=1; //Inicializa la constante blanca p= new Elemento();

}

public ConstanteBlanca(int x){ j=x;//Inicializa la constante blanca p=new Elemento();

}

public static void main(String args[])

{

ConstanteBlanca bf= new ConstanteBlanca();

}

}

Manual del Curso Java Básico

Métodos Constantes

Programa de Tecnología en Cómputo

Hay dos razones que justifican los métodos constantes. La primera es poner un “bloqueo” en el método para evitar que cualquier clase heredada varíe su significado. Esto se hace por razones de diseño cuando uno se quiere asegurar de que se mantenga el comportamiento del método durante la herencia, evitando que sea sobrescrito.

La segunda razón para los métodos constantes es la eficiencia. Si se puede hacer un método constante se ésta permitiendo al compilador convertir cualquier llamada a ese método en llamadas rápidas.

Para que un método sea constante, basta con anteponer la palabra final en su firma, ejemplo:

public final void nombreMetodo()

{

.

.

.

}

Clases Constantes

Cuando se dice que una clase entera es constante (precediendo su definición de la palabra clave final), se establece que no se desea heredar de esta clase o permitir a nadie más que lo haga. En otras palabras, por alguna razón el diseño de la clase es tal que nunca hay necesidad de hacer cambios, o por razones de seguridad no se desea la generación de subclases. De esta manera alternativa, se pueden estar tratando aspectos de eficiencia, y hay que asegurarse de que cualquier actividad involucrada con objetos de esta clase sea lo más eficiente posible.

//Cerebro.java

public class CerebroPequenio {

}

//Dinosaorio.java

public final class Dinosaurio { int i=7; int j=1; CerebroPequenio x= new CerebroPequenio(); public void f()

{}

}

//Jurasico.java

public class Jurasico { public static void main(String args[])

{

Dinosaurio n= new Dinosaurio();

Manual del Curso Java Básico

}

}

n.f();

n.i=40;

n.j++;

Programa de Tecnología en Cómputo

//public class SerEvolucionado extends Dinosaurio{ //} //Error: no se puede heredar de la clase constante.

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

6: Polimorfismo

El polimorfismo es la tercera característica esencial de un lenguaje orientado a objetos. Es una herramienta que provee otra dimensión de interfaz, capaz de separar el “qué” del “cómo”.

En el capítulo pasado aprendimos que con la herencia podemos tratar un objeto como “tipo de” su clase padre. Esta habilidad es esencial porque permite que objetos de varios tipos puedan ser tratados como objetos de un solo tipo, todo en el mismo código para trabajar con todos los distintos tipos de manera similar. El polimorfismo nos permite que distinguir entre los tipos de objetos que son similares. Dicha diferencia se expresa a través del comportamiento de los métodos que se heredan de la clase padre.

Veamos un ejemplo para recordar la conversión (Cast) hacia arriba:

//Nota.java //Herencia y upcasting.

public class Nota{ private int valor; private Nota(int val){ valor=val;} public static final Nota DO_MAYOR=new Nota(0); public static final Nota DO_SOSTENIDO=new Nota(1); public static final Nota SI_BEMOL =new Nota(2);

}

//Instrumento2.java

public class Instrumento2{ public void play(Nota n){ System.out.println("Instrumento.play()");

}

}

//Viento2.java

//Los instrumentos de viento son también tipo Instrumento! //porque tienen el mismo comportamiento. public class Viento2 extends Instrumento2{ //Redefiniendo un método public void play(Nota n){ System.out.println("Viento.play()");

}

}

//Musica2.java

public class Musica2{ public static void tonada(Instrumento2 i){ i.play(Nota.DO_SOSTENIDO);

}

public static void main(String[] args){ Viento2 flauta=new Viento2(); tonada(flauta); //Upcasting

}

}

Manual del Curso Java Básico

Programa de Tecnología en Cómputo

El método Musica.tonada() acepta un objeto Instrumento como referencia, pero también objetos derivado de éste. Por eso es que cualquier objeto Viento es aceptable para dicho método, ya que Viento hereda de Instrumento. Este programa parecería más directo sí el método tonada tuviera como argumento un objeto de tipo Viento. Esto presenta un punto esencial: si se hiciera esto se necesitará escribir un nuevo método tonada para cada tipo de Instrumento del sistema. Supóngase que se sigue este razonamiento y se añaden los instrumentos de Cuerda y Metal. Agregaremos las siguientes clases a nuestro directorio, renombremos y modifiquemos la clase Musica2 por Musica3 como se muestra a continuación:

//Metal.java public class Metal extends Instrumento2{ //Redefiniendo un método public void play(Nota n){ System.out.println("Metal.play()");

}

}

//Cuerda.java public class Cuerda extends Instrumento2{ //Redefiniendo un método public void play(Nota n){ System.out.println("Cuerda.play()");

}

}

//Musica3.java

public class Musica3{

public static void tonada(Viento2 v){ v.play(Nota.DO_SOSTENIDO);

}

public static void tonada(Cuerda c){

c.play(Nota.DO_SOSTENIDO);

}

public static void tonada(Metal m){ m.play(Nota.DO_SOSTENIDO);

}

public static void main(String[] args){

Viento2 f=new Viento2(); Cuerda c=new Cuerda(); Metal p=new Metal(); tonada(f); tonada( c ); tonada( p );

}

}

Como podemos o