MANUAL DE PRÁCTICAS ICCI

download MANUAL DE PRÁCTICAS ICCI

of 220

Transcript of MANUAL DE PRÁCTICAS ICCI

Introduccin a las Ciencias de la Computacin(con Java)Manual de prcticas

Canek Pelez V. Elisa Viso G.Facultad de Ciencias, UNAM

Introduccin y convencionesEn este libro ofrecemos las prcticas para un primer curso de programacin a nivel licenciatura utilizando el lenguaje de programacin Java. En ese sentido est dirigido a estudiantes de licenciatura que no tengan experiencia programando pero s los conocimientos mnimos para utilizar una computadora moderna. Todo el cdigo mostrado est escrito en Java, y se presenta en el contexto del sistema operativo Linux en particular; aunque cualquier sistema Unix capaz de ejecutar una Mquina Virtual de Java servir tambin. Por ello, los requisitos mnimos de hardware necesarios para realizar las prcticas aqu presentadas son exactamente los mismos que solicita la Mquina Virtual de Java de Sun Microsystems. Todas las prcticas tienen una seccin de desarrollo donde se ofrece un contexto terico para llevar a cabo los ejercicios. Si el estudiante y/o profesor consideran que la teora vista en clase es suciente para llevar a cabo cada prctica, el alumno puede sin ningn problema saltarse las secciones de desarrollo y resolver los ejercicios y preguntas directamente; pero creemos que la teora incluida en cada prctica ser de ayuda para el estudiante que decida consultarla. Se ha tratado de utilizar una serie de convenciones coherentes para poder distinguir los diferentes contextos en los que aparece cdigo en el texto. Todo el cdigo fue insertado en el texto, en el contexto del procesador de palabras A X, utilizando el paquete listings, de Carsten Heinz, a menos que el paquete fuera LTE incapaz de manejar el contexto. De cualquier forma, si no se poda usar el paquete listings, se trat de emular su funcionamiento. El cdigo que aparece dentro de bloques con lneas numeradas es cdigo que est pensado para que se escriba directamente en un archivo o que est sacado de algn archivo ya existente. Por ejemplo5 6 7 8 9 10 public class UsoMatriz2x2 { public s t a t i c void main ( S t r i n g [ ] args ) { Consola c ; c = new Consola ( "Matrices" ) ; ...

El cdigo que aparece en cajas y sin numeracin de lneas es cdigo pensado para

ii ejemplos cortos, no necesariamente existente o atado a alguna funcin en particular. Por ejemploc . i m p r i m e l n ( "hola mundo" ) ;

Los comandos pensados para que el alumno los teclee en su intrprete de comandos estn escritos utilizando el tipo typewriter, y se utiliza el carcter # para representar el prompt del intrprete. Por ejemplo# javac -classpath interfaz1.jar:. Matriz2x2.java

Cada vez que aparece un nuevo concepto en el texto, se resalta utilizando el tipo slanted. Por ejemplo: Generalmente diremos que la clase principal o clase de uso es la clase que mandamos ejecutar desde el intrprete de comandos con java. Cuando un nombre o nombres aparezca entre < y >, signica que puede ser reemplazado por cadenas proporcionadas por el alumno. Por ejemplo# java

signica que puede ser reemplazado por cualquier nombre de clase. Tambin signicar que puede ser reemplazado por ms de un trmino, si el contexto lo permite. Por ejemplo en# javac

podr ser reemplazado por varios archivos de clases.

ndice general1. Ant y el compilador de Java 2. Usar y modicar clases 3. Variables, tipos y operadores 4. Interfaces y clases por dentro 5. Estructuras de control y listas 6. Herencia 7. Entrada/salida y arreglos 8. Recursin 9. Manejo de excepciones 10. Interfaces grcas 11. Ant y archivos Jar 12. *Hilos de ejecucin y enchufes A. El resto de las leyes 1 7 21 41 71 87 103 121 129 143 181 191 209

Prctica: Ant y el compilador de Java

1

Every non-trivial program has at least one bug. Corollary 1 - A sufcient condition for program triviality is that it have no bugs. Corollary 2 - At least one bug will be observed after the author leaves the organization. Murphys Laws of Computer Programming #1

MetaQue el alumno comience a utilizar Ant para compilar, detectar errores de sintaxis y semnticos, y generar bytecode ejecutable.

2

DesarrolloJava es un lenguaje compilado, lo que quiere decir que un compilador se encarga de transformar las instrucciones de alto nivel de un programa, en cdigo que la Mquina Virtual de Java (Java Virtual Machine o JVM) puede ejecutar.

Actividad 1.1 Invoca al compilador de Java sin ningn argumento, con la siguiente lnea de comandos: # javac (Nota que slo debes escribir javac y despus teclear Enter ; el # slo representa el prompt de tu intrprete de comandos). Anota todas las opciones que se pueden pasar al compilador.

El compilador de Java no slo genera el cdigo ejecutable por la JVM; tambin detecta errores de sintaxis y semnticos, mostrando en qu lnea ocurren. Adems, el compilador tiene lo que se conoce como recuperacin; al encontrar el primer error no se detiene, trata de continuar tanto como sea posible y seguir encontrando errores. Esto ltimo es importante porque le permite al programador corregir un mayor nmero de errores por cada compilacin, en lugar de tener que compilar cada vez que quiere encontrar el siguiente error.

AntEs posible compilar cualquier proyecto de Java utilizando el compilador desde la lnea de comandos. Sin embargo, conforme un proyecto crece en tamao y complejidad, la lnea de comandos va siendo cada vez ms restrictiva. Para ayudarnos con la compilacin de proyectos en Java, utilizaremos Ant. Ant es un programa (escrito en Java, por cierto), que lee un archivo de conguracin en XML, y de ah obtiene la informacin necesaria para compilar un proyecto.

Actividad 1.2 Visita la pgina del proyecto Ant, en http://ant.apache.org/

Ant y el compilador de Java Actividad 1.3 De la pgina de las prcticas1 , baja el archivo practica1. tar .gz, y descomprmelo con la siguiente lnea de comandos: # tar zxvf practica1.tar.gz Despus, trata de compilar la prctica: # cd practica1 # ant compile Cuntos errores marca? Los entiendes? El signicado de cada error est dado por la traduccin del ingls.

3

El compilador de Java, a travs de Ant, muestra en qu lnea de un programa ocurre el error (si encuentra alguno). Si se utiliza un editor como XEmacs, y si est congurado de manera adecuada, se puede compilar dentro de XEmacs y saltar directamente a la lnea en donde ocurre el error.

Actividad 1.4 Abre el archivo UsoReloj.java en XEmacs (est en el directorio icc1/practica1), y compila haciendo C-c C-v C-b , tecleando compile y dando Enter despus. Debe abrirse un segundo buffer en XEmacs donde se muestran los errores encontrados por el compilador. Cmbiate a ese buffer haciendo C-x o y teclea Enter en la primera lnea que marque error. Qu sucede? En caso de que no funcione, puedes intentar cargar el archivo de proyecto que utiliza la prctica. Para esto, en XEmacs haz click en el men JDE Project Project File Load. Si no existe ningn men JDE, tu XEmacs no est congurado como es debido.

Una vez que un programa est libre de errores, el compilador genera un archivo en bytecode. La JVM ejecuta bytecode, un formato binario desarrollado para que los ejecutables de Java puedan ser utilizados en varias plataformas sin necesidad de recompilar. El bytecode puede copiarse directamente a cualquier mquina que tenga una JVM, y ejecutarse sin cambios desde ah. A eso se le conoce como portabilidad a nivel binario. Muchos otros lenguajes de programacin tienen portabilidad a nivel de cdigo, y otros no tienen ningn tipo de portabilidad.1

La pgina de las prcticas est disponible en http://abulaa.fciencias.unam.mx/practicas.

4

El archivo build.xmlAnt utiliza un archivo de conguracin escrito en XML. XML es el Lenguaje Extendible para el Formato de Documentos (Extensible Markup Language en ingls), y es, sencillamente, una manera de representar informacin.

Actividad 1.5 Busca en la red informacin acerca de XML. Puedes comenzar en http://www.w3c.org

Para motivos de esta prctica, slo es necesario saber que un documento XML tiene etiquetas (tags), que cada etiqueta tiene una etiqueta de inicio (del tipo ) y una etiqueta nal (del tipo ), y que estas etiquetas estn anidadas:1 2 3 ... 4 5 6 . . . 7 8 ... 9

Esto es ilegal en XML:< e t i q u e t a 1 >< e t i q u e t a 2 > . . . < / e t i q u e t a 1 >< / e t i q u e t a 2 >

No est anidado. Lo correcto es:< e t i q u e t a 1 >< e t i q u e t a 2 > . . . < / e t i q u e t a 2 >< / e t i q u e t a 1 >

En XML, es equivalente escribir a , para representar etiquetas vacas. Todas las etiquetas de un documento XML pueden tener atributos, que son de la forma:< e t i q u e t a a t r i b u t o 1 ="valor1" a t r i b u t o 2 ="valor2">

La informacin que representa el archivo build.xml es la necesaria para manejar un proyecto en Java a travs de Ant. Por ello, la etiqueta raz del archivo build.xml (la etiqueta que envuelve a todas las dems), se llama project (proyecto).

Ant y el compilador de Java

5

En el archivo build.xml de esta prctica, dentro de la etiqueta raz slo hay etiquetas target (objetivo). Cada objetivo es una tarea que Ant puede ejecutar al ser llamado. Los objetivos de nuestro archivo build.xml son: compile run docs clean Compila la prctica. Ejecuta la prctica, compilndola si no ha sido compilada. Genera la documentacin JavaDoc de la prctica (veremos esto la prxima prctica). Limpia la prctica de bytecode, documentacin, o ambos.

Para decirle a Ant que ejecute un objetivo, slo se lo pasamos como parmetro (tienen que hacer esto en el directorio donde est el archivo build.xml):# ant compile # ant run

Si no se le pasa ningn objetivo a Ant, se ejecutar compile. Esto es porque la etiqueta project del archivo build.xml tiene un atributo llamado default, cuyo valor es compile:2 < p r o j e c t name="practica1" d e f a u l t ="compile" b a s e d i r =".">

La sintaxis del archivo build.xml la iremos analizando en las siguientes prcticas del curso.

Ejercicios1. Corrige los errores que aparecen en la prctica, hasta que el programa compile y genere el bytecode. Utiliza los mensajes del compilador2 para determinar la lnea del error y en qu consiste. Todos los errores estn en la clase UsoReloj, que est en el archivo UsoReloj.java (las clases de Java generalmente estn en un archivo llamado como la clase, con extensin .java). No toques los dems archivos. (Puedes darle una mirada a los dems archivos de la prctica; sin embargo, el funcionamiento de estos archivos ser discutido posteriormente.) 2. Una vez que el programa compile, ejectalo con la siguiente lnea de comandos (estando en el directorio practica1):2

S, los mensajes estn en ingls. Ni modo.

6# ant run

3. Ya que tu prctica compile y se ejecute como es debido, haz# ant clean

para borrar los archivos que se hayan compilado. Despus haz# ant

y ve cuntos archivos dice ant que va a compilar (al momento de correr Ant con el objetivo compile, dice cuntos archivos se prepara a compilar). Una vez que termine de compilar, ejecuta el comando# touch src/icc1/practica1/UsoReloj.java

y despus vuelve a correr Ant. Notas alguna diferencia? Explcala.

Preguntas1. Qu errores encontraste al compilar esta prctica? Explica en qu consisten. 2. Los errores que encontraste, de qu tipo crees que sean, sintcticos o semnticos? Justica tu respuesta. 3. Cuntos archivos en bytecode (los que tienen extensin .class) se generaron? 4. Cul crees que sea la explicacin del comportamiento de Ant despus de hacer el ejercicio 3? Justica tu respuesta.

Prctica: Usar y modicar clases

2

Bugs will appear in one part of a working program when another unrelated part is modied. Murphys Laws of Computer Programming #2

MetaQue el alumno aprenda cmo funcionan las clases, cmo se construyen objetos de una cierta clase, qu son mtodos y variables de clase, y cmo se invocan las funciones de una clase.

ObjetivosAl nalizar la prctica el alumno ser capaz de:

8 entender qu es una clase; entender qu es una interfaz; declarar y construir objetos con el operador new; entender qu son los mtodos y variables de una clase; hacer que el objeto llame a las funciones de su clase con el operador . (punto); modicar las funciones de una clase para que sus objetos tengan un comportamiento distinto; y generar la documentacin de una clase para saber qu funciones provee sin necesidad de leer el cdigo directamente.

DesarrolloEn la prctica pasada, aprendimos cmo utilizar Ant y el compilador de Java para generar bytecode ejecutable, y ejecutamos un programa que mostraba un reloj en la pantalla. En esta prctica analizaremos ms detenidamente la clase UsoReloj para ver cmo funciona el programa, y modicaremos ciertas partes de la clase ClaseReloj.

ClasesLas clases de la prctica pasada son ClaseReloj, VistaRelojAnalogico y UsoReloj. Adems tenemos dos interfaces: Reloj y VistaReloj. Veremos las interfaces en detalle ms adelante en esta misma prctica. Los objetos de la clase ClaseReloj son como la maquinaria de un reloj de verdad. La maquinaria es la que se encarga de que el reloj funcione de cierta manera (de que avance o retroceda, etc.) Los objetos de la clase VistaRelojAnalogico son como la parte externa de un reloj de verdad. Piensen en el Big Ben; los objetos de la clase VistaRelojAnalogico son la torre, las manecillas y la cartula con los nmeros. En otras palabras, los objetos de la clase VistaRelojAnalogico no saben cmo funciona un reloj (ni tienen porqu saberlo). Slo se encargan de mostrar la informacin del reloj al mundo exterior, poniendo las manecillas donde deben estar. La clase UsoReloj es como el dueo de un reloj de verdad. Posee al reloj, lo pone a la hora requerida y en general hace con l todo lo que se puede hacer con un reloj. La clase principal del programa es UsoReloj, en el sentido de que es en esta clase donde se utilizan las otras dos (ClaseReloj y VistaRelojAnalogico). Generalmente diremos que la clase principal o clase de uso es la clase que mandamos ejecutar desde el intrprete de comandos con java o con ant run.

Usar y modicar clases

9

La clase principal siempre tendr el punto de entrada a nuestros programas; este punto de entrada es la funcin main.1

Cmo Ant compila y ejecuta programasEn la prctica anterior compilamos nuestro programa con:# ant compile

Tambin as compilaremos esta prctica.

Actividad 2.1 De la pgina del libro, baja el archivo practica2.tar.gz y descomprmelo igual que el de la prctica anterior. Compila la prctica.

Si abrimos el archivo build.xml (que es prcticamente igual al de la prctica anterior), notaremos que el objetivo compile est denido de la siguiente manera:4 5 6 7 8 < t a r g e t name="compile"> < j a v a c s r c d i r ="src" d e s t d i r ="build" debug="true" d e b u g l e v e l ="source" / >

Lo primero que hace este cdigo es crear un directorio (dentro del directorio donde se encuentra el archivo build.xml). Este directorio (build) sirve para que ah se guarde el bytecode que se genera al compilar nuestro cdigo. El tener dos directorios separados para nuestro cdigo fuente (src, por source en ingls, fuente, origen), y otro para nuestros archivos construidos (build, por construir en ingls), nos permite una ms fcil organizacin de nuestro cdigo. En particular, limpiar nuestro directorio de trabajo se limita a borrar el directorio build. Para crear el directorio, utilizamos la tarea mkdir (las tareas son etiquetas que Ant provee para hacer cosas):51

Los trminos funcin, mtodo, y (aunque cada vez ms en desuso) procedimiento sern considerados iguales en sta y las dems prcticas del curso. En orientacin a objetos suele hacerse hincapi en que son mtodos, no funciones, pero nosotros relajaremos esa regla ya que en Java slo existen mtodos y no hay rezn para diferenciarlos de lo que en otros lenguajes son las funciones.

10

Noten que la etiqueta termina con / >, lo que quiere decir que no tiene cuerpo. Despus de crear el directorio build, mandamos llamar al compilador de Java, javac, dicindole dnde est nuestro cdigo fuente (srcdir), dnde queremos que se guarden los binarios (destdir), que queremos que el cdigo tenga smbolos de depuracin (debug), y el nivel de depuracin que queremos (debuglevel). Para esto, utilizamos la tarea javac:6 7 < j a v a c s r c d i r ="src" d e s t d i r ="build" debug="true" d e b u g l e v e l ="source" / >

Tambin es una etiqueta sin cuerpo. Con esta informacin, Ant busca los archivos fuente (.java) en el directorio de fuentes, o en sus subdirectorios, y la versin compilada la deja en el directorio build. Para ejecutar nuestro programa utilizamos# ant run

El objetivo run est denido de la siguiente manera:9 10 11 12 13 14 15 < t a r g e t name="run" depends="compile"> < j a v a classname="icc1.practica2.UsoReloj"> < / classpath> < / java>

El objetivo tiene un atributo, depends, cuyo valor es compile. Esto quiere decir que el objetivo run depende del objetivo compile. En otras palabras, el objetivo run no puede ser llamado si antes no ha sido llamado el objetivo compile. Si llamamos al objetivo run sin haber llamado al objetivo compile, Ant automticamente lo llamar. Para ejecutar el programa, utilizamos la tarea java:10 11 12 13 14 < j a v a classname="icc1.practica2.UsoReloj"> < / classpath> < / java>

La tarea tiene un atributo, classname, cuyo valor es icc1.practica2.UsoReloj. Este atributo le dice a Ant qu clase queremos ejecutar; en este caso UsoReloj. Lo que precede a UsoReloj, icc1.practica2, es el paquete de la clase UsoReloj. Veremos qu son exactamente los paquetes ms adelante.

Usar y modicar clases

11

(La diferencia entre el build.xml de esta prctica y la anterior, es que el anterior tena como valor del atributo classname a icc1.practica1.UsoReloj). Esta es la primera tarea que s tiene cuerpo. El cuerpo es11 12 13 < / classpath>

El cuerpo es una estructura de tipo ruta (path en ingls). En otras palabras, le dice a Java dnde buscar las clases necesarias para la ejecucin de un programa. Esta estructura a su vez tiene un cuerpo que est formado por la etiqueta pathelement, que en su atributo path dice qu ruta queremos utilizar. En este caso es el directorio build, donde estn nuestras clases compiladas. La etiqueta classpath puede aceptar varios directorios en su cuerpo.

El mtodo mainAcabamos de ver cmo ejecutar un programa en Java utilizando Ant. Lo que hace la JVM al ejectuar una clase es ver el bytecode de la clase llamada (UsoReloj en nuestra prctica), buscar la funcin main dentro de la misma, y ejecutarla. Si no existe un mtodo main en esa clase, la JVM termina con un mensaje de error. Por eso se le llama punto de entrada a la funcin main; es lo primero que se ejecuta en un programa en Java. Todas las clases en Java pueden tener su propio mtodo main; sin embargo, en nuestras prcticas generalmente slo una clase tendr mtodo main. El mtodo main de una clase se ejecuta nicamente cuando la clase es invocada desde el sistema operativo (shell).

Actividad 2.2 Abre el archivo UsoReloj.java en XEmacs y localiza la funcin main.

Noten que todas las partes de una clase de Java estn formadas a partir de bloques, anidados unos dentro de otros, y todos adentro del bloque ms grande, que es el de la clase misma. Un bloque comienza con un {, y termina con un }. Si descontamos el bloque de la clase, todos los bloques son de la forma:{ < e x p r e s i n 1 >; < e x p r e s i n 2 >; ... < e x p r e s i n N> ;

}

12

Esto es un bloque de ejecucin. En l, las expresiones del bloque se ejecutan en el orden en que aparecen. A un bloque tambin se le suele llamar cuerpo. Cada vez que un bloque comienza, la sangra del programa debe aumentar; esto facilita la lectura de cdigo.

Declaracin y construccin (instancing) de objetosYa dijimos que la clase UsoReloj es como el dueo de un reloj de verdad. Pero antes de poder usarse un reloj, debe adquirirse. Para poder adquirir un objeto de la clase ClaseReloj, se tiene que declarar. Declarar un objeto de una cierta clase es como decir en qu mano se va a usar o asignarle un cajn donde se va a guardar. La declaracin es simplemente la reserva de cmo se va a localizar al reloj una vez que se tenga. En la clase UsoReloj lo declaramos as:14 Reloj r e l ;

Podramos hacerlo con14 ClaseReloj r e l ;

pero queremos utilizar la interfaz Reloj. Ahorita veremos en qu consisten las interfaces. As queda declarado un objeto que implementa la interfaz Reloj, y el nombre con el que haremos referencia al objeto ser rel. Declarar un objeto es como cuando llenamos un catlogo para hacer compras por correo o por Internet; hacemos explcito qu queremos (en este caso un objeto que implementa la interfaz Reloj), pero an no lo tenemos. Para poseerlo, necesitamos crearlo. Para crear o construir (instanciar)2 un objeto, se utiliza el operador new. En la clase UsoReloj lo hacemos de la siguiente manera:17 r e l = new C l a s e R e l o j ( ) ;

El operador new llama al constructor de la clase ClaseReloj. Veremos con ms detalle a los constructores en la siguiente prctica. Es hasta el momento de consruir el objeto cuando ste comienza a existir propiamente; ahora podemos comenzar a utilizarlo.2

Del ingls instancing, aunque la palabra en espaol no es del todo adecuada

Usar y modicar clases Actividad 2.3 En el archivo UsoReloj.java, en su funcin main, localiza dnde se declara al objeto rel que implementa la interfaz Reloj, y tambin dnde se construye un objeto de la clase ClaseReloj.

13

Dentro de la funcin main de la clase UsoReloj ya tenemos un objeto de la clase ClaseReloj que se llama rel. Pero dijimos que los objetos de la clase ClaseReloj son como la maquinaria de un reloj. Necesitamos la caja, la parte externa. Para poner a la maquinaria la cartula y las manecillas, necesitamos un objeto que implemente la interfaz VistaReloj. De igual manera, necesitamos declarar al objeto y construirlo. En la clase UsoReloj hacemos esto:V i s t a R e l o j rep ; ... rep = new V i s t a R e l o j A n a l o g i c o ( r e l ) ;

Y de esta manera ya tenemos un objeto de la clase VistaRelojAnalogico llamado rep. Noten que el constructor de la clase VistaRelojAnalogico no es igual al de la clase ClaseReloj. El constructor de la clase ClaseReloj no tena parmetros:r e l = new C l a s e R e l o j ( )

mientras que el constructor de la clase VistaRelojAnalogico tiene un parmetrorep = new V i s t a R e l o j A n a l o g i c o ( r e l )

El parmetro es rel; veremos con ms detalle los parmetros en las siguientes prcticas. La construccin de objetos se puede leer as: al construir un objeto de la clase VistaRelojAnalogico le pasamos como parmetro un objeto de la clase ClaseReloj. Esto es como si atornillramos la maquinaria del reloj a la caja; hacemos que la representacin del reloj est atada a su funcionamiento interno (y tiene sentido que sea en ese orden, ya que la caja de un reloj no tiene razn de ser sin el mecanismo)3 .Aqu algunos de ustedes estarn pensando que no tiene mucho sentido separar la maquinaria de la caja; despus de todo, cuando uno compra un reloj lo hace con la maquinaria y la caja juntas (aunque muchos relojes nos vienen con varios extensibles intercambiables, por ejemplo). Esta es una de las caractersticas del paradigma orientado a objetos. Al tener separadas la parte que muestra al reloj de la parte que maneja su funcionamiento, es posible cambiar la representacin del reloj sin tener que reescribir todo el programa (podramos escribir una clase llamada VistaRelojDigital, que en lugar de usar manecillas utilizara el formato HH:MM:SS para representar el reloj, y ya no tenemos que preocuparnos del funcionamiento interno del reloj, que lo maneja la clase ClaseReloj).3

14

Uso de mtodosLos mtodos o funciones de una clase son los servicios a los cuales un objeto de esa clase puede tener acceso. En la clase UsoReloj, el objeto rel de la clase ClaseReloj slo utiliza cuatro mtodos: avanzaSegundo, avanzaMinuto, avanzaHora y ponTiempo. Para llamar a una funcin utilizamos el operador . (punto). En la clase UsoReloj, llamamos a avanzaSegundo de la siguiente manera:22 r e l . avanzaSegundo ( ) ;

En general, para llamar una funcin se utiliza:. < nombreFuncin> ( < parmetro_1 > , . . . , < parmetro_N > ) ;

Lo que hace entonces el operador . (punto) es ver de qu clase es el objeto (un objeto siempre sabe de qu clase es ejemplar4 ), buscar la funcin por su nombre, y ejecutarla pasndole los parmetros.

Actividad 2.4 En el archivo UsoReloj.java, busca dnde se llama a las funciones avanzaSegundo, avanzaMinuto y avanzaHora y ponTiempo de la clase ClaseReloj.

Estos mtodos hacen lo que su nombre indica; avanzaSegundo hace que el secundero se mueva hacia adelante un segundo. Las otras dos (avanzaMinuto y avanzaHora) hacen lo mismo con el minutero y las horas respectivamente. El mtodo ponTiempo cambia el valor del secundero, del minutero y de las horas de un solo golpe. Recibe tres enteros como parmetro, as que para poner el reloj a las 7 con 22 minutos y 34 segundos tenemos que hacer esto:r e l . ponTiempo ( 7 , 2 2 , 3 4 ) ;

Ahora, una de las desventajas de separar el funcionamiento del reloj de su representacin, es que esta ltima no cambia automticamente cuando el estado del reloj cambia. As que explcitamente tenemos que decirle a la representacin (a la caja) que se actualice. Para esto, la clase VistaRelojAnalogico nos ofrece el mtodo que se llama actualiza, que no recibe parmetros:234

rep . a c t u a l i z a ( ) ;

Usamos el trmino ejemplar en lugar de la traduccin literal instancia, que viene del ingls instance, ya que instancia tiene otro signicado en espaol.

Usar y modicar clases

15

En la funcin main de la clase UsoReloj, utilizamos tambin la funcin espera de la clase VistaRelojAnalogico. Esta funcin slo espera un determinado nmero de segundos (que es el parmetro que recibe) antes de que nada ms ocurra.Actividad 2.5 Abre el archivo ClaseReloj.java y busca la denicin de las funciones utilizadas en UsoReloj.java. Si ests utilizando XEmacs como editor, puedes abrir el archivo y hacer C-s para comenzar una bsqueda interactiva. Esto quiere decir que mientras vayas tecleando, XEmacs ir buscando en el archivo lo que vayas escribiendo. Prubalo; abre el archivo ClaseReloj.java, haz C-s y teclea avanzahora (as, todas minsculas). Para cuando hayas terminado, XEmacs estar marcando la primera ocurrencia de la cadena avanzaHora en el archivo (observa que XEmacs ignora la diferencia entre maysculas y minsculas). Esa primera ocurrencia no es todava la denicin del mtodo avanzaHora; si vuelves a dar C-s , XEmacs marcar ahora s la denicin que buscas. Utiliza C-s cuando quieras buscar algo rpido en XEmacs.

Variables locales y de claseEn la funcin main de la clase UsoReloj, declaramos dos variables, r y rep; la primera para referirnos a nuestro objeto de la clase ClaseReloj, y la segunda para referirnos a nuestro objeto de la clase VistaRelojAnalogico. En la clase ClaseReloj, puedes ver al inicio del archivo las siguientes lneas:20 21 22 p r i v a t e i n t hora ; p r i v a t e i n t minuto ; p r i v a t e i n t segundo ;

Tambin hora, minuto y segundo son variables. Qu diferencia tienen de r y rep? La primera diferencia es obvia; la declaracin de hora, minuto y segundo est precedida por un private. La palabra clave private es un modicador de acceso; los veremos con ms detalle en la prctica 3. La segunda diferencia tambin es muy fcil de distinguir: r y rep estn declaradas dentro de una funcin (main en este caso), mientras que hora, minuto y segundo estn declaradas dentro de la clase. La diferencia es importante; las variables declaradas dentro de una funcin son variables locales, mientras que las variables declaradas dentro de una clase son variables de clase o variables miembro.

16 Desde que vieron la declaracin de hora, minuto y segundo, debi ser obvio que sirven para que guardemos los valores del mismo nombre de nuestros objetos de la clase Reloj. Las variables de clase sirven justamente para eso; para guardar el estado de un objeto. Al valor que tienen en un instante dado las variables de clase de un objeto se le llama el estado de un objeto. Veremos ms acerca de las variables en las siguientes prcticas.

Mtodos desde adentroYa vimos algunos mtodos de la clase ClaseReloj que se utilizan en la clase UsoReloj. Para qu sirven los mtodos? Dijimos que las variables de clase guardan el estado de un objeto. La misin de los mtodos de una clase es justamente cambiar ese estado, o para obtener informacin acerca de l de alguna manera. Por ejemplo, las funciones avanzaSegundo, avanzaMinuto y avanzaHora cambian el estado de nuestro objeto r, y la funcin actualiza cambia el estado de nuestro objeto rep, para que mueva nuestras manecillas a la hora actual.5 Veamos el mtodo avanzaHora de la clase ClaseReloj (recuerda que est en el archivo ClaseReloj.java):151 152 153 154 155 156 public void avanzaHora ( ) { t h i s . hora ++; i f ( t h i s . hora > R e l o j . HORAS_POR_DIA) { t h i s . hora = 0 ; } }

Qu hace el mtodo? En primer lugar, no recibe ningn parmetro. Esto tiene sentido, ya que la funcin siempre har lo mismo (avanzar una hora), y por lo tanto no necesita ninguna informacin externa para hacerlo. Despus, est la lnea:152 t h i s . hora++

El operador ++ le suma un 1 a una variable. Veremos ste y ms operadores en las siguientes prcticas. Sumarle un 1 a hora es justamente lo que queremos (que las horas avancen en uno). Pero, qu ocurre cuando son las 12 y le sumamos 1? En un reloj de verdad, la hora da la vuelta y se pone de nuevo en 1. En particular en nuestra clase ClaseReloj estamos suponiendo que 12 es igual a cero (como ocurre con muchos relojes digitales),Algunas veces tambin se utilizan funciones que no cambian el estado de un objeto, ni tampoco lo obtienen; el mtodo espera es un ejemplo.5

Usar y modicar clases

17

y entonces cuando hora vale 0, la manecilla de las horas apunta hacia el 12. As que cuando hora valga 11 y se llame a avanzaHora, nuestro reloj deber poner hora en 0. Eso es justamente lo que hacen las lneas153 154 155 i f ( t h i s . hora > R e l o j . HORAS_POR_DIA) { t h i s . hora = 0 ; }

La condicional if verica lo que hay dentro de su parntesis, y si es verdad, ejecuta el bloque que le sigue. Este if puede leerse si hora es mayor que once, entonces haz que hora valga cero. Veremos con ms detalle a if y otras condicionales ms adelante. Las dems funciones de la clase ClaseReloj que hemos visto hasta ahora funcionan de manera similar a avanzaHora. Deniremos nuestras propias funciones en prcticas siguientes.

InterfacesHemos estado trabajando con la clase ClaseRejoj; sin embargo, el objeto que declaramos fue de la interfaz Reloj. Qu es una interfaz?

Actividad 2.6 Abre y examina el contenido de la interfaz Reloj, en el archivo Reloj.java.

Si examinamos el archivo Reloj.java, notaremos que una interfaz es una especie de clase vaca. Sus mtodos no tienen cuerpo; no hacen nada. Para qu nos sirve entonces? Una interfaz es un contrato. Especica qu ofrece una clase; pero no dice cmo lo hace. La clase ClaseReloj implementa (implements) la interfaz Reloj. Con eso, se compromete a cumplir el contrato; a encontrar un modo de hacer que funcionen los mtodos que declara la interfaz. Veremos con ms detalle a las interfaces cuando veamos herencia.

Comentarios dentro de los programasEn las clases ClaseReloj y UsoReloj, habrs visto varias partes del cdigo que empezaban con //, o que estaban encerradas entre /* y */ . A estas partes se les llama comentarios, y sirven para que el programador haga anotaciones acerca de lo que est escribiendo. El compilador ignora los comentarios; sencillamente se los salta.

18 Los comentarios que empiezan con // son de una lnea. El compilador ignora a partir de //, y lo sigue haciendo hasta que encuentra un salto de lnea o que acaba el archivo, lo que ocurra primero. Los comentarios que empiezan con /* son por bloque. El compilador ignora absolutamente todo lo que encuentra a partir de /* , y lo sigue haciendo hasta que encuentre un */ . No se vale tener comentarios de este tipo anidados; esto es invlido:/* / * Comentario i n v l i d o ( e s t anidado ) . * / / *

Tambin es invlido abrir un comentario /* y no cerrarlo nunca. Si el compilador ve un /* , y despus llega al n del archivo sin encontrar un */ , entonces marcar un error.

JavaDocCmo podemos saber qu mtodos nos ofrece una clase? La manera ms sencilla es abrir el archivo de la clase y leer el cdigo. Sin embargo, esto puede resultar tedioso, si la clase es larga y compleja. Java ofrece un pequeo programa que nos permite observar los interiores de una clase de manera ordenada y elegante. El programa se llama JavaDoc, y lee programas escritos en Java, con lo que genera pginas HTML que podemos ver utilizando cualquier navegador, como Firefox o el Internet Explorer. Como casi todo lo que tiene que ver con desarrollo en Java, Ant tiene una tarea para manejar a JavaDoc, y sorprendentemente se llama javadoc. En nuestro build.xml lo mandamos llamar dentro del objetivo docs:1 2 3 4 < t a r g e t name="docs">

Lo nico que le decimos a la tarea javadoc es dnde estn los archivos fuente, en qu directorio queremos que genere la documentacin, y de qu paquetes queremos que la genere (vimos un poco arriba que el paquete que estamos utilizando es icc1.practica2.

Usar y modicar clases Actividad 2.7 Invoca a JavaDoc sin parmetros con la siguiente lnea: # javadoc Anota todas las opciones que se podran utilizar.

19

Actividad 2.8 Genera la documentacin de la prctica con el comando # ant docs Con ayuda de tu ayudante revisa la documentacin generada.

La documentacin generada muestra, entre otras cosas, los mtodos y constructores de las clases, incluyendo los parmetros que reciben. Ms adelante veremos cmo utilizar los comentarios de Java para ayudar a JavaDoc a generar informacin.

Ejercicios1. Modica la funcin avanzaMinuto de la clase ClaseReloj para que cada vez que sea llamada, en lugar de avanzar un minuto avance diez. Recuerda que la clase ClaseReloj est en el archivo ClaseReloj.java. Compila y ejecuta de nuevo el programa para ver si tus cambios son correctos. 2. Con la documentacin que generaste, lee qu parmetros recibe el segundo constructor de la clase VistaRelojAnalogico, y utilzalo en el mtodo main de la clase UsoReloj, para que al ejecutar el programa la ventana del reloj sea ms grande o pequea. Juega con varios valores de x y y, compilando y ejecutando cada vez para comprobar tus resultados. Nota que en el primer ejercicio slo debes modicar el archivo ClaseReloj.java, y en el segundo ejercicio slo debes modicar UsoReloj.java. No es necesario que toques, y ni siquiera que mires VistaRelojAnalogico.java. Los interiores de VistaRelojAnalogico.java los veremos ms adelante, cuando hayamos manejado ya interfaces grcas.

20

Preguntas1. Entiendes cmo funciona el mtodo avanzaHora? Justica tu respuesta. 2. Entiendes cmo funciona el mtodo ponTiempo? Justica tu respuesta.

Prctica: Variables, tipos y operadores

3

The subtlest bugs cause the greatest damage and problems. Corollary - A subtle bug will modify storage thereby masquerading as some other problem. Murphys Laws of Computer Programming #3

MetaQue el alumno aprenda a utilizar los tipos bsicos de Java y sus operadores, y que entienda el concepto de referencia.

ObjetivosAl nalizar la prctica el alumno ser capaz de:

22 utilizar la clase Consola para hacer salida en pantalla; manejar variables locales, tipos bsicos y literales de Java; entender lo que son referencias y manejar operadores y expresiones.

DesarrolloUn programa (en Java o cualquier lenguaje de programacin) est escrito para resolver algn problema, realizando una o ms tareas. En el caso particular de Java, se utiliza la orientacin a objetos para resolver estos problemas. Utilizar la orientacin a objetos quiere decir, entre otras cosas, abstraer el mundo en objetos y a estos objetos agruparlos en clases. En la prctica anterior, por ejemplo, utilizamos las clases ClaseReloj y VistaRelogAnalogico, que abstraan el funcionamiento de un reloj y su representacin externa al implementar las interfaces Reloj y VistaReloj. Vamos a comenzar a resolver problemas utilizando orientacin a objetos. Esto quedar dividido en dos partes fundamentales: la primera ser identicar los objetos que representan nuestro problema, agruparlos en clases y denir precisamente el comportamiento (las funciones) que tendrn para que resuelvan nuestro problema. La segunda parte es un poco ms detallada. Una vez denido el comportamiento de una clase, hay que sentarse a escribirlo. Esto se traduce en implementar los mtodos de la clase. Para implementarlos, es necesario manejar las partes bsicas o atmicas del lenguaje: las variables, sus tipos, y sus operadores. En esta prctica jugaremos con esta parte fundamental del lenguaje Java; en la siguiente utilizaremos lo que aprendamos aqu para comenzar a escribir nuestras clases.

Una clase de pruebaPara jugar con variables, vamos a necesitar un bloque de ejecucin donde ponerlas, o sea un mtodo, y ya que necesitamos un mtodo, vamos a necesitar tambin una clase donde ponerlo. Un problema es que no sabemos hacer todava mtodos, as que utilizaremos el mtodo main, que ya utilizamos en las prcticas pasadas. Escribamos pues una clase llamada Prueba, y utilicemos el mtodo main de ella. Nuestra clase Prueba quedara como sigue:

Variables, tipos y operadores

23

1 2 3 4 5 6 7 8

package i c c 1 . p r a c t i c a 3 ; public class Prueba { public s t a t i c void main ( S t r i n g [ ] args ) { } }

An no hemos visto paquetes, as que por ahora no explicaremos qu signica la lnea1 package i c c 1 . p r a c t i c a 3 ;

Por ahora slo necesitamos saber que eso signica que el archivo Prueba.java debe estar en un directorio llamado practica3, y que ste a su vez debe estar en un directorio llamado icc1.Actividad 3.1 Baja el archivo practica3.tar.gz, y descomprmelo como lo hemos hecho en prcticas pasadas. El archivo contiene ya un build.xml para esta prctica, y la estructura de directorios necesaria (o sea src/icc1/practica3). Dentro de ese directorio crea tu archivo Prueba.java para tu clase Prueba. Si ests usando XEmacs (y ste est bien congurado), y pones esto: en la primera lnea, cada vez que abras el archivo, XEmacs har disponibles varias funcionalidades especiales para editar archivos de Java. Entre otras cosas, colorear de forma especial la sintaxis del programa, y te permitir llamar a Ant con C-c C-v C-b ./* * jde * */

Como recordars de la prctica anterior, utilizamos el directorio src para poner nuestro cdigo fuente (y as tambin lo especiacmos en el build.xml). Y como nuestro paquete es icc1.practica3, dentro de src creamos el directorio icc1, y dentro de ste otro llamado practica3. Con el build.xml proporcionado podemos compilar y ejecutar el programa como venamos hacindolo hasta ahora. Podemos comprobar (viendo el archivo build.xml) que ahora la clase que ejecutamos en el objetivo run es icc1.practica3.Prueba. Esto es la clase Prueba del paquete icc1.practica3. Varios deben estar ahora hacindose algunas preguntas: Qu quiere decir exactamente public class Prueba? Para qu es la palabra static ? De dnde sali el constructor de Prueba?

24 Todas esas preguntas las vamos a contestar en la siguiente prctica; en sta nos vamos a concentrar en variables, tipos y operadores. La clase Prueba se ve un poco vaca; sin embargo, es una clase completamente funcional y puede ser compilada y ejecutada.Actividad 3.2 Compila y ejecuta la clase (desde el directorio donde est el archivo build.xml): # ant compile # ant run No va a pasar nada interesante (de hecho no va a pasar nada), pero con esto puedes comprobar que es una clase vlida, pues compila bien y no termina con un mensaje de rror al ejecutarse.

Ahora, queremos jugar con variables, pero no va a servir de mucho si no vemos los resultados de lo que estamos haciendo. Para poder ver los resultados de lo que hagamos, vamos a utilizar a la clase Consola.

La clase ConsolaPara tener acceso a la pantalla y ver los resultados de lo que le hagamos a nuestras variables, vamos a utilizar la clase Consola. Esta clase nos permitir, entre otras cosas, escribir en la pantalla.Actividad 3.3 De la pgina referida al nal de las prcticas, baja el archivo icc1.jar, y ponlo en el directorio de la prctica 3.

Cmo vamos a utilizar la clase Consola dentro de nuestra clase Prueba? Primero, debemos decirle a nuestra clase acerca de la clase Consola. Esto lo logramos escribiendoimport i c c 1 . i n t e r f a z . Consola ;

antes de la declaracin de nuestra clase. Veremos ms detalladamente el signicado de import cuando veamos paquetes. En segundo lugar, cuando compilemos tambin tenemos que decirle al compilador dnde buscar a la clase Consola. Para poder hacer esto, necesitamos modicar nuestro build.xml.

Variables, tipos y operadores Actividad 3.4 Modica el archivo build.xml cambiando la lnea:6 7 < j a v a c s r c d i r ="src" d e s t d i r ="build" debug="true" d e b u g l e v e l ="source" / >

25

por6 7 < j a v a c s r c d i r ="src" d e s t d i r ="build" debug="true" d e b u g l e v e l ="source" c l a s s p a t h ="icc1.jar" / >

El classpath es donde Java (el compilador y la mquina virtual) buscan clases extras. En ltimo lugar, cuando ejecutemos de nuevo tenemos que decirle a la JVM dnde est nuestra clase Consola; para esto tambin modicamos nuestro build.xml.

Actividad 3.5 Modica el archivo build.xml cambiando el objetivo run de la siguiente manera:10 11 12 13 14 15 16 17 < t a r g e t name="run" depends="compile"> < j a v a classname="icc1.practica3.Prueba" f o r k ="true"> < / classpath> < / java>

De la misma manera, estamos aadiendo el archivo icc1.jar al classpath para que la JVM lo encuentre al ejecutar el programa. Qu podemos hacer con la clase Consola? De hecho, podemos hacer muchas cosas, que iremos descubriendo poco a poco conforme avancemos en el curso; pero por ahora, nos conformaremos con utilizarla para mostrar los valores de nuestras variables.

Actividad 3.6 Con la ayuda de un navegador, ve la documentacin generada de la clase Consola. Se irn explicando y utilizando todos los mtodos de la clase conforme se avance en el material.

26 Para mostrar informacin con la consola, necesitamos crear un objeto de la clase consola y con l llamar a los mtodos imprime o imprimeln. Por ejemplo, modica el mtodo main de la clase Prueba de la siguiente manera:11 2 3 4 5 6 7 8 9 10 11 12 package i c c 1 . p r a c t i c a 3 ; import i c c 1 . i n t e r f a z . Consola ; public class Prueba { public s t a t i c void main ( S t r i n g [ ] args ) { Consola c ; c = new Consola ( "Valores de variables" ) ; c . imprime ( "Hola mundo." ) ; }

}

Compila y ejecuta la clase. El resultado lo puedes ver en la gura 3.1.Figura 3.1 Consola

Para terminar el programa, cierra la ventana de la consola. Analicemos las tres lneas que aadimos a la funcin main:81

Consola c ; para representar los espacios dentro de las cadenas.

Observa que estamos utilizando

Variables, tipos y operadores

27

En esta lnea slo declaramos un nuevo objeto de la clase Consola llamado c.9 c = new Consola ( "Valores de variables" ) ;

En esta lnea construimos un objeto de la clase Consola y lo asociamos a c. El constructor que usamos recibe como parmetro una cadena, que es el ttulo de la ventana de nuestra consola. Al construir el objeto, la ventana con nuestra consola se abre automticamente.10 c . imprime ( "Hola mundo." ) ;

El mtodo imprime de la clase Consola hace lo que su nombre indica; imprime en la consola la cadena que recibe como parmetro, que en nuestro ejemplo es "Hola mundo.". Dijimos que podamos utilizar los mtodos imprime e imprimeln para mostrar informacin en la consola. Para ver la diferencia, imprime otra cadena en la consola:9 10 11 12 Consola c ; c = new Consola ( "Valores de variables" ) ; c . imprime ( "Hola mundo." ) ; c . imprime ( "Adis mundo." ) ;

Compila y ejecuta la clase. El resultado lo puedes ver en la gura 3.2.Figura 3.2 Resultado de imprime en la consola

28 Ahora, utilicemos el mtodo imprimeln en lugar de imprime:13 14 c . i m p r i m e l n ( "Hola mundo." ) ; c . i m p r i m e l n ( "Adis mundo." ) ;

Si compilas y ejecutas la clase, vers algo parecido a la gura 3.3.Figura 3.3 Resultado de imprimeln en la consola

La diferencia entre imprime e imprimeln es que la segunda imprime un salto de lnea despus de haber impreso la cadena que le pasamos como parmetro. El salto de lnea en Java est representado por el carcter \n. Otra forma de conseguir el mismo resultado es hacer13 14 c . imprime ( "Hola mundo.\n" ) ; c . imprime ( "Adis mundo.\n" ) ;

o incluso13 c . imprime ( "Hola mundo.\nAdis mundo.\n" ) ;

La clase Consola ofrece muchos mtodos, que iremos utilizando a lo largo de las dems prcticas. En sta slo veremos imprime e imprimeln.

Variables, tipos y operadores Actividad 3.7 Crea la clase Prueba en el archivo Prueba.java y realiza (valga la redundancia) pruebas con imprime e imprimeln.

29

Variables locales, tipos bsicos y literalesYa hemos trabajado con variables locales. En la prctica pasada, reloj y vista eran variables locales del mtodo main en la clase UsoReloj. En esta prctica, c es un variable local de la funcin main en la clase Prueba. Las variables locales se llaman as porque slo son visibles localmente. Cuando escribamos funciones, no van a poder ver (y por lo tanto no podrn usar) a c porque esta variable slo puede ser vista dentro de la funcin main. Se conoce como el alcance de una variable a los lugares dentro de un programa desde donde puede ser vista la variable. Recordemos la declaracin de reloj y vista de la prctica anterior:Reloj r e l o j ; ... VistaReloj vista ;

Las dos son variables locales, pero tienen una diferencia muy importante: son de tipos diferentes. Java es un lenguaje de programacin fuertemente tipicado, lo que signica que una variable tiene un nico tipo durante toda su vida, y que por lo tanto nunca puede cambiar de tipo. Esto quiere decir que lo siguiente sera invlido:v i s t a = new C l a s e R e l o j ( ) ;

Si intentan compilar algo as, javac se va a negar a compilar la clase; les va a decir que vista no es de tipo ClaseReloj. Vamos a empezar a declarar variables. Para declarar una variable, tenemos que poner el tipo de la variable, seguido del nombre de la variable:int a;

Si queremos usar varias variables de un solo tipo, podemos declararlas todas juntas:int a , b , c , d;

30

Con eso declaramos una variable de cierto tipo, pero, qu son los tipos? Para empezar a ver los tipos de Java, declaremos un entero llamado a en el mtodo main.7 8 9 10 11 12 13 public s t a t i c void main ( S t r i n g [ ] args ) { Consola c ; c = new Consola ( "Valores de variables" ) ; / / Declaramos un e n t e r o " a " ; int a;

}

La variable a es de tipo entero ( int ). Java tiene algunos tipos especiales que se llaman tipos bsicos. Los tipos bsicos dieren de todos los otros tipos en que NO son objetos; no tienen mtodos ni variables de clase, y no tienen constructores. Para inicializar (que no es igual que construir) una variable de tipo bsico, sencillamente se le asigna el valor correspondiente, por ejemplo:a = 5;

Java tiene ocho tipos bsicos, que puedes consultar en la tabla 3.1.Tabla 3.1 Tipos bsicos de Java

Nombrebyte short int long oat double char boolean

Descripcin Enteros con signo de 8 bits en complemento a dos Enteros con signo de 16 bits en complemento a dos Enteros con signo de 32 bits en complemento a dos Enteros con signo de 64 bits en complemento a dos Punto otante de 32 bits de precisin simple Punto otante de 64 bits de precisin doble Carcter de 16 bits Valor booleano (verdadero o falso)

En el ejemplo de arriba, qu representa el 5? El 5 representa una literal, en este caso de tipo entero. Las literales son valores que no estn atados a una variable. Todos los tipos bsicos tienen literales:int double char boolean entero ; doble ; caracter ; booleano ; Contina en la siguiente pgina

Variables, tipos y operadores

31Contina de la pgina anterior

entero doble caracter booleano

= = = =

1234; 13.745; a ; true ;

En general, a cualquier serie de nmeros sin punto decimal Java lo considera una literal de tipo int , y a cualquier serie de nmeros con punto decimal Java lo considera una literal de tipo double. Si se quiere una literal de tipo long se tiene que poner una L al nal, como en 1234L, y si se quiere un otante hay que poner una F al nal, como en 13.745F. No hay literales explcitas para byte ni para short. Las nicas literales de tipo boolean son true y false. Las literales de carcter son a, Z, +, etc. Para los carcteres como el salto de lnea o el tabulador, las literales son especiales, como \n o \t. Si se necesita la literal del carcter \, se utiliza \\. Si se necesita un carcter internacional, se puede utilizar su cdigo Unicode2 , por ejemplo, \u0041 representa el carcter A (el entero que sigue a \u est escrito en hexadecimal, y deben escribirse los cuatro dgitos). La fuerte tipicacin de Java se aplica tambin a sus tipos bsicos:i n t a = 13; / / C d i g o v l i d o i n t b = t r u e ; / / C d i g o i n v l i d o !

Sin embargo, el siguiente es cdigo vlido tambin:f l o a t x = 12; byte b = 5 ; int a = b;

Si somos precisos, la literal 12 es de tipo int (como dijimos arriba); y sin embargo se lo asignamos a una variable de tipo oat . De igual forma, b es de tipo byte, pero le asignamos su valor a a, una variable de tipo int . Dejaremos la explicacin formal de por qu esto no viola la fuerte tipicacin hasta que veamos conversin explcita de datos; por ahora, basta con entender que un entero con signo que cabe en 8 bits (los de tipo byte), no tiene ninguna dicultad hacer que quepa en un entero con signo de 32 bits, y que todo entero con signo que quepa en 32 bits, puede ser representado por un punto otante de 32 bits. Por la misma razn, el siguiente cdigo s es invlido:Unicode es un cdigo de carcteres pensado para reemplazar a ASCII. ASCII slo tena (originalmente) 127 caracteres y despus fue extendido a 255. Eso basta para el alfabeto latino, con acentos incluidos, y algunos carcteres griegos; pero es completamente intil para lenguas como la china o japonesa. Unicode tiene capacidad para 65,535 caracteres, lo que es suciente para manejar estos lenguajes. Java es el primer lenguaje de programacin en soportar nativamente Unicode.2

32int a = 1.2; int b = 5; byte c = b ;

El primero debe ser obvio; no podemos hacer que un punto otante sea representado por un entero. Sin embargo, por qu no podemos asignarle a c el valor b, cuando 5 s cabe en un entero de 8 bits con signo? No podemos porque al compilador de Java no le interesa qu valor en particular tenga la variable b. Lo nico que le importa es que es de tipo int , y un int es muy probable que no quepa en un byte. El compilador de Java juega siempre a la segura.

Actividad 3.8 Prueba los pequeos ejemplos que se han visto, tratando de compilar todos (utiliza el mtodo main para tus ejemplos). Ve qu errores manda el compilador en cada caso, si es que manda.

Cmo vamos a imprimir en nuestra consola nuestros tipos bsicos? Pues igual que nuestras cadenas:int a = 5; c . imprimeln ( a ) ;

Los mtodos imprime e imprimeln de la clase Consola soportan todos los tipos de Java. Una ltima observacin respecto a variables locales (sean stas de tipo bsico u objetos). Est claro que para usar una variable local en un mtodo, tiene que estar declarada antes de ser usada. Esto es obvio porque no podemos usar algo antes de tenerlo. Empero, hay otra restriccin: no podemos usar una variable antes de inicializarla; el siguiente cdigo no compila:int a; i n t b = a ; / / No podemos usar l a v a r i a b l e a todava . . .

Estamos tratando de usar a sin que haya sido inicializada. Esto es invlido para el compilador de Java. Dijimos que esto se aplica a tipos bsicos y objetos, y ms arriba dijimos que inicializar no era lo mismo que construir. Esto es porque tambin podemos inicializar variables que sean objetos sin necesariamente construir nada. Para entender esto, necesitamos comprender qu son las referencias.

Variables, tipos y operadores

33

ReferenciasCuando hacemosConsola c ;

dijimos que estamos declarando un objeto de la clase Consola. As se acostumbra decir, y as lo diremos siempre a lo largo de estas prcticas. Sin embargo, formalmente hablando, estamos declarando una variable de tipo referencia a un objeto de la clase Consola. Una referencia es una direccin en memoria. Al construir en c con newc = new Consola ( ) ;

lo que hace new es pedirle a la JVM que asigne memoria para poder guardar en ella al nuevo objeto de la clase Consola. Entonces new regresa la direccin en memoria del nuevo objeto, y se guarda en la variable c. Esto es importante; las variables de referencia a algn objeto tienen valores que son direcciones de memoria, as como las variables de tipo entero tienen valores que son enteros en complemento a dos, o las variables de tipo booleano tienen valores que son true o false. Si despus de construir p hacemosConsola c2 ; c2 = c ;

entonces ya no estamos construyendo a c2 (no se est asignando memoria a ningn nuevo objeto). Lo que estamos haciendo es inicializar a c2 con el valor de c, o sea, con la direccin de memoria a la que hace referencia c. Despus de eso, c y c2 son dos variables distintas, que tienen el mismo valor, o sea, que hacen referencia al mismo objeto3 . Todas las referencias (no importa de qu clase sean) tienen una nica literal, que es null. sta es una referencia que por denicin es invlida; no apunta nunca a ninguna direccin vlida de la memoria. La referencia null es muy utilizada para varios propsitos, y en particular sirve para inicializar variables de objetos que an no deseamos construir. Veremos ms ejemplos con null en las siguientes prcticas. Una vez denidas las referencias, podemos dividir a las variables de Java en dos; toda variable de Java es de un tipo bsico, o alguna referencia. No hay otras. Adems de esto, todas las referencias apuntan a algn objeto, o tienen el valor null.3

Se suele decir tambin que apuntan al mismo objeto.

34

OperadoresSabemos ya declarar todas las posibles variables de Java. Una vez que tengamos variables, podemos guardar valores en ellas con el operador de asignacin =; pero adems debemos poder hacer cosas interesantes con los valores que puede tomar una variable. Para hacer cosas interesantes con nuestras variables, es necesario utilizar operadores. Los operadores de Java aparecen en la tabla 3.2.

Tabla 3.2 Operadores de Java.

Operandos posjo unario posjo unario posjo n-ario posjo unario posjo unario unario prejo unario prejo unario prejo unario prejo unario prejo unario prejo unario prejo unario prejo binario injo binario injo binario injo binario injo binario injo binario injo binario injo binario injo binario injo binario injo binario injo

Asocia tividad derecha derecha derecha izquierda izquierda derecha derecha izquierda izquierda izquierda izquierda izquierda izquierda izquierda izquierda izquierda izquierda izquierda izquierda

Smbolo[ ] . () ++ ++ + ! new () * / % + > izquierda >>> izquierda < izquierda

Variables, tipos y operadores Tabla 3.2 Operadores de Java

35

Contina de la pgina anterior

Operandos binario injo binario injo binario injo binario injo binario injo binario injo binario injo binario injo binario injo ternario injo binario injo binario injo binario injo binario injo binario injo binario injo binario injo binario injo binario injo binario injo binario injo binario injo

Asocia tividad izquierda izquierda izquierda izquierda izquierda izquierda izquierda izquierda izquierda izquierda derecha derecha derecha derecha derecha derecha derecha derecha derecha derecha derecha derecha

Smbolo>= instanceof == != & ^ | && || ? : = += = *= /= %= >>= >= &= ^= |=

Descripcin relacional mayor o igual que relacional ejemplar de relacional, igual a relacional, distinto de AND de bits XOR de bits OR de bits AND lgico OR lgico Condicional aritmtica asignacin autosuma y asignacin autoresta y asignacin autoproducto y asignacin autodivisin y asignacin automdulo y asignacin autocorrimiento derecho y asignacin autocorrimiento izquierdo y asignacin autocorrimiento derecho con propagacin y asignacin auto-AND de bits y asignacin auto-XOR de bits y asignacin auto-OR de bits y asignacin

Los operadores en general se comportan como uno esperara; si uno haceint a = 3 + 2;

entonces a toma el valor 5. Todos los operadores tienen un dominio especco; cosas comotrue + false ;

36

no tienen sentido. Cuando se opera con tipos distintos, pero compatibles, se asume el tipo ms general. Por ejemplo, si tenemosint a = 2; float x = 1.5;

entonces a+x es de tipo oat . Los operadores funcionan de acuerdo al tipo de los operandos. Si se dividen dos enteros con el operador / , se hace divisin entera; el resultado se trunca al mayor entero menor o igual al resultado de la divisin. Si se dividen otantes o dobles, el resultado es la divisin real (o lo ms cercano, de acuerdo a la precisin simple o doble de cada tipo). Hay varios operadores en la tabla que funcionan sobre bits. Esto quiere decir que operan sobre un valor de tipo entero, pero jndose en los bits, ms que en el valor en s. Veamos un ejemplo.i n t a = 13; i n t b = 19; int c = a | b;

La variable a vale 13 y la b vale 19. En bits esto es a = 00000000000000000000000000001101 b = 00000000000000000000000000010011 (recordemos que los enteros tienen 32 bits). Para no tener que escribir tanto, usamos hexadecimal para representar los valores y podemos verlos como 0x0000000D y 0x00000013. Cul es valor de la variable c entonces? Estamos usando el OR para bits; se aplica un OR a cada uno de los bits del entero, y el resultado es c = 00000000000000000000000000011111 o bien 0x0000001F, que a su vez es el valor 31 en base 10. Siempre hay que tener en cuenta que los tipos enteros de Java (byte, short, int , long) tienen signo; eso quiere decir que el bit ms signicativo en estos tipos guarda el signo. La tabla 3.2 est ordenada en orden de precedencia. La precedencia de los operadores determina el orden en que sern aplicados. Por ejemplo en

Variables, tipos y operadoresint a = 3 + 2 * 5;

37

el valor de a es 13, no 25, ya que la precedencia de la multiplicacin es mayor que la de la suma. Si queremos que la suma se aplique antes, tenemos que haceri n t a = (3 + 2) * 5;

Pueden utilizar la tabla de operadores para saber qu operador tiene precedencia sobre cules; sin embargo, en general es bastante intuitivo. En caso de duda, poner parntesis nunca hace dao (pero hace que el cdigo se vea horrible; los parntesis son malosMR ).4 Los operadores relacionales (, =) funcionan sobre tipos numricos, y regresan un valor booleano. La igualdad y la desigualdad (==, !=) funcionan sobre todos los tipos de Java. En el caso de las referencias, == regresar true si y slo si las referencias apuntan a la misma posicin en la memoria; al mismo objeto. Hay que notar que la asignacin (=) es muy diferente a la igualdad (==). La asignacin toma el valor de la derecha (se hacen todos los cmputos que sean necesarios para obtener ese valor), y lo asigna en la variable de la izquierda. El valor debe ser de un tipo compatible al de la variable. Tambin hay algunos operadores de conveniencia, los llamados auto operadores. Son +=, =, *=, /=, %=, >>=, >=, &=, ^=, y |=. La idea es que si tenemos una variable entera llamada a, entoncesa += 1 0 ;

es exactamente igual aa = a + 10;

E igual con cada uno de los auto operadores. Como el caso de sumarle (o restarle) un uno a una variable es muy comn en muchos algoritmos, los operadores ++ y hacen exactamente eso. Pero hay dos maneras de aplicarlos: prejo y post jo. Si tenemosint a = 5; i n t b = a ++;

entonces a termina valiendo 6, pero b termina valiendo 5. Esto es porque el operador regresa el valor de la variable antes de sumarle un uno, y hasta despus le suma el uno a la variable. En cambio en4

Parenthesis are evilTM .

38int a = 5; i n t b = ++a ;

las dos variables terminan valiendo 6, porque el operador primero le suma un uno a a, y despus regresa el valor de la variable. Los operadores lgicos && (AND) y || (OR) funcionan como se espera que funcionen (p q es verdadero si y slo si p y q son verdaderos, y p q es verdadero si y slo si p es verdadero o q es verdadero), con una pequea diferencia: funcionan en corto circuito. Esto quiere decir que si hacemosi f ( a < b && b < c )

y a < b es falso, entonces el && ya no comprueba su segundo operando. Ya sabe que el resultado va a dar falso, as que ya no se molesta en hacer los clculos necesarios para ver si b < c es verdadero o falso. Lo mismo pasa si el primer operando de un || resulta verdadero. Es importante tener en cuenta esto, porque aunque en lgica matemtica nos dijeron que p q q p, a la hora de programar esto no es 100 % cierto. Un operador bastante til es la condicional aritmtica (?:). Funciona de la siguiente manera:int z = (a < b) ? 1 : 0;

Si a es menor que b, entonces el valor de z ser 1. Si no, ser 0. La condicional aritmtica funciona como un if chiquito, y es muy til y compacta. Por ejemplo, para obtener el valor absoluto de una variable (digamos a) slo necesitamos haceri n t b = ( a < 0 ) ? a : a ;

Hay varios operadores que funcionan con referencias. Algunos funcionan con referencias y con tipos bsicos al mismo tiempo (como = y ==, por ejemplo); pero otros son exclusivos de las referencias. Los operadores ms importantes que tienen las referencias son new, que las inicializa, y . (punto), que nos permite interactuar con las partes de un objeto. Hay otros operadores para los objetos, y otros para tipos bsicos, que iremos estudiando en las prcticas que siguen.

ExpresionesUna vez que tenemos variables (tipos bsicos u objetos), literales y operadores, obtenemos el siguiente nivel en las construcciones de Java. Al combinar una o ms variables o literales con un operador, tenemos una expresin.

Variables, tipos y operadores

39

Las expresiones no son atmicas; pueden partirse hasta que lleguemos a variables o literales y operadores. Podemos construir expresiones muy rpido:a ++; // (a++); // (a++)*3; // 5 + ( ( a + + ) * 3 / 2 + 5 / r e l o j . dameMinuto ( ) * r e l o j // Esto es una e x p r e s i n . Esto tambin . Tambin . . dameHoras ( ) ) ; S , tambin .

En general, todas las expresiones regresan un valor. No siempre es as, sin embargo, como veremos en la siguiente prctica. Podemos hacer expresiones tan complejas como queramos (como muestra el ltimo de nuestros ejemplos arriba), siempre y cuando los tipos de cada una de sus partes sean compatibles. Si no lo son, el compilador de Java se va a negar a compilar esa clase. El siguiente nivel en las construcciones de Java lo mencionamos en la prctica pasada: son los bloques. En la prxima prctica analizaremos nivel de construccin ms importante de Java: las clases.

EjerciciosTodas estas pruebas las tienes que realizar dentro del mtodo main de tu clase Prueba. 1. Trata de obtener el mdulo5 ( %) de un otante. 2. Declara un oat llamado x, y asgnale la literal 1F. Declara un oat llamado y y asgnale la literal 0.00000001F. Declara un tercer oat llamado z y asgnale el valor que resulta de restarle y a x. Imprime z en tu consola. 3. Imprime el valor de la siguiente expresin: 1>>1. Ahora imprime el valor de la siguiente expresin 1>>1. 4. Declara dos variables booleanas p y q. Asgnales a cada una un valor (true o false, t decide), e imprime el valor de la expresin (p q) en sintaxis de Java. Despus imprime el valor de la expresin p q utilizando la consola.

Cambia los valores de p y q para hacer las cuatro combinaciones posibles, imprimiendo siempre el resultado de las dos expresiones. Con esto demostrars la regla de De Morgan caso por caso.El resultado que se obtiene de la expresin a % b, con a y b enteros, es el residuo entero lo que sobra que resulta al dividir a entre b.5

40

Preguntas1. Crees que sea posible asignar el valor de un otante a un entero? Cmo crees que funcionara? 2. Observa el siguiente cdigoint a = 1; int b = 2; int c = 3; ( a > 3 && ++a

57

y la tarea javadoc quedara:1

Compila y ejecuta usando tu build.xml. Si quieres compilar dentro de XEmacs, utiliza uno de los archivos pjr.el de las prcticas anteriores, y ponlo junto al archivo build.xml.

Modicadores de accesoQu pasa si hacemos lo siguiente en el mtodo main de nuestra clase de uso?4 5 6 7 8 9 10 11 12 13 14 public s t a t i c void main ( S t r i n g [ ] args ) { Consola c ; c = new Consola ( "Matrices" ) ; MatrizCuadrada m; m = new M a t r i z 2 x 2 ( 1 , 2 , 3 , 4 ) ; m. a = 1 0 ; c . i m p r i m e l n (m. g e t D e t e r m i n a n t e ( ) ) ; } }

El valor que se imprima en la consola ser -2, aunque el determinante de nuestra matriz (despus de la modicacin que le hicimos en la lnea 11) sea 34, porque el determinante se calcula en el momento en que el objeto se construye. Lo que pasa aqu es que el estado de nuestro objeto queda inconsistente. Y eso pasa porque modicamos directamente una variable de clase de nuestro objeto m al hacerm. a = 1 0 ;

Podramos hacer la solemne promesa de nunca modicar directamente una variable de clase; pero eso no basta. Tenemos que garantizar que eso no ocurra. No debe ocurrir nunca.

58 A esto se le llama el acceso de una variable de clase (que no es lo mismo que el alcance). Una variable puede tener acceso pblico, de paquete, protegido o privado. Las variables locales no tienen modicadores de acceso ya que slo existen dentro de un mtodo. Cuando una variable de clase tiene acceso pblico, en cualquier mtodo de cualquier clase puede ser vista y modicada. Cuando tiene acceso privado, slo dentro de los mtodos y constructores de los objetos de la clase a la que pertenece puede ser vista y modicada. Los accesos de paquete y protegidos los veremos cuando veamos paquetes y herencia, respectivamente. Restringir el acceso a una variable de clase nos permite controlar cmo y cundo ser modicado el estado de un objeto. Con esto garantizamos la consistencia del estado, pero tambin nos permite cambiar las variables privadas de un objeto, y que ste siga siendo vlido para otras clases que lo usen; como nunca ven a las variables privadas, entonces no importa que las quitemos, les cambiemos el nombre o tipo o le aadamos alguna. El acceso es el principal factor del encapsulamiento de datos. Por todo esto, siempre es bueno tener las variables de clase con un acceso privado. Vamos a cambiarle el acceso a las variables de clase de Matriz2x2. Nuestras variables no tenan ningn acceso especicado, por lo que Java les asigna por omisin el acceso de paquete; para motivos prcticos y con lo que hemos visto, el acceso es pblico. Para cambirselo a privado, slo tenemos que hacer3 class M a t r i z 2 x 2 implements MatrizCuadrada { 4 p r i v a t e double a ; 5 p r i v a t e double b ; 6 p r i v a t e double c ; 7 p r i v a t e double d ; 8 p r i v a t e double d e t e r m i n a n t e ;

Los modicadores para pblico, protegido y de paquete son public, protected y package respectivamente. Aunque no es necesario poner package para que una variable de clase tenga acceso de paquete, en estas prcticas ser requisito que el acceso de los mtodos y las variables sea explcito. Los mtodos tambin tienen modo de acceso, y tambin es de paquete por omisin. Hemos usado public porque queramos tener completa nuestra interfaz antes de implementar nuestra clase. El acceso en los mtodos tiene el mismo signicado que en las variables de clase; si un mtodo es privado, no podemos usarlo ms que dentro de los mtodos de la clase, y si un mtodo es pblico, se puede usar en cualquier mtodo de cualquier clase. Los mtodos privados son generalmente funciones auxiliares de los mtodos pblicos y de paquete, y al hacerlos privados podemos agregar ms o quitarlos cuando queramos, y las clases que usen a nuestra clase no se vern afectadas. El encapsula-

Interfaces y clases por dentro

59

miento de datos facilita la modularizacin de cdigo. Tambin ser requisito que todos los mtodos tengan el acceso explcito, aunque sea de paquete. Los constructores tambin tienen modo de acceso, y como en muchas otras cosas funciona de manera idntica que para mtodos. Sin embargo, si tenemos un constructor privado, signica que no podemos construir objetos de esa clase fuera de la misma clase; no podramos construir objetos de la clase en una clase de uso, por ejemplo. Veremos en un momento por qu quisisemos hacer eso. No slo las variables de clase, los mtodos y constructores tienen modo de acceso. Las mismas clases tienen modo de acceso, y tambin por omisin es de paquete. Una clase privada parece no tener sentido; y no obstante lo tiene. Veremos ms adelante cundo podemos hacer privado el acceso a una clase; por ahora, cambiemos el acceso de nuestra clase a pblico:3 public class M a t r i z 2 x 2 implements MatrizCuadrada { 4 ...

Ya que nuestras variables de clase son privadas, cmo hacemos para poder verlas o modicarlas fuera de la clase? Como dijimos arriba, Java tiene la convencin de utilizar mtodos set/get para esto. Los mtodos set cambiarn el valor de una variable, y los get lo obtendrn. Por ejemplo, para la variable a:70 71 72 73 74 75 76 77 78 79 public double getA ( ) { return this . a ; } public void setA ( double a ) { this . a = a ; t h i s . d e t e r m i n a n t e = t h i s . a * t h i s . dt h i s . b * t h i s . c ; } ...

Puede parecer engorroso; pero la justicacin se hace evidente en esta ltima funcin. Cada vez que modiquemos un componente de la matriz, actualizaremos automticamente el valor del determinante. Con esto dejamos bien denido cmo ver y cmo modicar el estado de un objeto, y garantizamos que sea consistente siempre. El acceso es parte fundamental del diseo de una clase. Si hacemos un mtodo o variable de clase con acceso pblico, habr que cargar con l siempre, ya que si lo quitamos o lo hacemos privado, es posible que existan aplicaciones que lo utilizaran, y entonces stas ya no serviran.

60Actividad 4.4 Implementa los mtodos getA, getB, getC, getD y setA, setB, setC y setD. Puedes observar que no habr mtodo setDeterminante, ya que el determinante depende de las componentes de la matriz.

Otros modicadoresHay dos modicadores ms para las variables y mtodos de Java. El primero de ellos es nal . Una variable nal slo puede ser inicializada una vez; y generalmente ser al momento de ser declarada. Una vez inicializada, ya no cambia de valor nunca. Su valor es nal. Las variables nales pueden ser de clase o bien locales. Cuando tengamos una literal que utilizamos en muchas partes del cdigo, y que dentro de la ejecucin del programa nunca cambia (por ejemplo, el IVA en un programa de contabilidad), siempre es mejor declarar una variable nal para denirlo, y as si por alguna razn nos vuelven a subir el IVA,3 en lugar de cambiar todos los lugares donde aparezca la literal, slo cambiamos el valor que le asignamos a la variable nal. Tambin facilita la lectura del cdigo. Otros lenguajes de programacin tienen constantes. Las variables nales de Java no son constantes exactamente; pero pueden emular a las constantes de otros lenguajes. Hay mtodos nales tambin, pero su signicado lo veremos cuando veamos herencia. El otro modicador es static . Una variable de clase esttica es la misma para todos los objetos de una clase. No es como las variables de clase normales, que cada objeto de la clase tiene su propio cajn; las variables estticas son compartidas por todos los objetos de la clase, y si un objeto la modica, todos los dems objetos son afectados tambin. No hay variables locales estticas (no tendran sentido). Tambin hay mtodos estticos. Un mtodo esttico no puede tener acceso a las variables de clase no estticas; no puede hacer this. a ninguna variable. El mtodo main por ejemplo siempre es esttico. Para tener acceso a una variable esttica o a un mtodo esttico se puede utilizar cualquier objeto de la clase, o la clase misma. Si la clase Matriz2x2 tuviera una variable esttica var por ejemplo, podramos hacer Matriz2x2.var para tener acceso a ella (si var fuese pblica, por supuesto). Hay clases cuyos objetos necesitan pasar por un proceso de construccin ms estricto que las clases normales. Para este tipo de clases, que suelen llamarse clases fbrica (o factory classes en ingls), lo que se hace es que tienen constructores privados, y3

O ms raro; que lo bajen.

Interfaces y clases por dentro

61

entonces se usan mtodos estticos para que creen los objetos de la clase usando las restricciones que sean necesarias. Si queremos una variable privada, que adems sea esttica, y adems nal, hay que hacerpublic s t a t i c f i n a l i n t n = 0 ; / / Hay que i n i c i a l i z a r s i es f i n a l !

por ejemplo. No se puede cambiar el orden; lo siguiente no compilapublic f i n a l s t a t i c i n t n = 0 ; / / Hay que i n i c i a l i z a r s i es f i n a l !

Bsicamente eso es todo lo necesario para escribir una clase.

CadenasEn la prctica anterior vimos tipos bsicos, pero varios de ustedes han de haber observado que constantemente mencionbamos cadenas sin nunca denirlas. Por ejemplo, al constructor de la clase Consola le pasamos una cadena:4Consola c ; c = new Consola ( "Ttulo de mi consola" ) ;

Las cadenas (strings en ingls) son objetos de Java; pero son los nicos objetos que tienen literales distintas de null y denido el operador +. Adems, son los nicos objetos que podemos crear sin utilizar new. Las cadenas son consideradas por todo esto un tipo bsico; pero no por ello dejan de ser objetos, con todos los atributos y propiedades de los objetos. Las literales de las cadenas las hemos usado a lo largo de estas prcticas; son todos los carcteres que estn entre comillas: "hola mundo" ; "adis..." ; "En un lugar de la Mancha de cuyo nombre..." ; Para declarar una variable de tipo cadena, declaramos un objeto de la clase String:String a;4

Observa que estamos utilizando

para representar los espacios dentro de las cadenas.

62

pero no es necesario construirlo con new; el asignarle una literal de cadena basta. Las dos construcciones de la siguiente pgina son equivalentes.a = "hola mundo" ; a = new S t r i n g ( "hola mundo" ) ;

Esta es una comodidad que Java otorga; pero en el fondo las dos construcciones son exactamente lo mismo (en ambas la JVM asigna memoria para el objeto), aunque en la primera no tengamos que escribir new String ( ) . Adems de tener literales y construccin implcita, las cadenas son el nico objeto en Java que tiene denido el operador +, y sirve para concatenar cadenas:S t r i n g h , m, a ; h = "hola " ; m = "mundo" ; a = h + m;

En este ejemplo, la variable a termina valiendo "hola mundo". Lo bonito del caso es que no slo podemos concatenar cadenas; podemos concatenar cadenas con cualquier tipo de Java. Si hacemosi n t edad = 1 5 ; String a; a = "Edad: " + 1 5 ;

la cadena resultante es " Edad: 15". Y funciona para enteros, otantes, booleanos carcteres e incluso referencias. Por eso nuestro mtodo toString poda sumar dobles con cadenas; realmente estaba concatenando cadenas. Por dentro, una cadena es una sucesin de caracteres uno detrs del otro. La cadena a que vimos arriba tiene esta forma por dentro:h0

o1

l2

a3 4

m u5 6

n7

d8

o9

Las cadenas son objetos de slo lectura. Esto quiere decir que podemos tener acceso al carcter m de la cadena "hola mundo", pero no podemos cambiar la m por t para que esa misma cadena sea "hola tundo". Sin embargo, podemos crear un nuevo objeto cadena que diga "hola tundo" a partir de "hola mundo", y asignarlo de nuevo a la variable:

Interfaces y clases por dentroString a; a = "hola mundo" ; a = a . s u b s t r i n g ( 0 , 5 ) + "t" + a . s u b s t r i n g ( 6 , 1 0 ) ;

63

Ahora a representa a "hola tundo"; pero hay que entender que a a se le asign un nuevo objeto (construido a partir del original), no que se modic el anterior (y adems, utiliza tres objetos temporales para construir el nuevo objeto; el primero a.substring (0,5) , el segundo "t", y el tercero a.substring (6,10) ). Las cadenas son parte fundamental de la aritmtica de Java; ofrecen muchas funciones y utilidades que en muchos otros lenguajes de programacin es necesario implementar a pie. Regresando a la cadena "hola tundo", su longitud es 10 (tiene 10 carcteres), y siempre puede saberse la longitud de una cadena haciendoint longitud = a . length ( ) ;

Las cadenas pueden ser tan grandes como la memoria lo permita. Cada uno de los carcteres de la cadena pueden recuperarse (leerse), pero no modicarse. Java ofrece adems muchas funciones para construir cadenas a partir de otras cadenas. Por ejemplo, si queremos slo la subcadena "tundo", slo necesitamos hacerString b; b = a . substring (5 ,10);

De nuevo; esto regresa un nuevo objeto sin modicar el anterior. La cadena a seguir siendo "hola tundo". Hay que notar que substring regresa todos los carcteres entre el ndice izquierdo y el ndice derecho menos uno sin incluir al carcter en la posicin del ndice derecho . Esto es para que la longitud de la subcadena sea el ndice derecho menos el ndice izquierdo. Puede que slo deseemos un carcter, entonces podemos usarchar c = a . c h a r A t ( 5 ) ;

Y esto regresa el carcter (tipo char) m. Si tratamos de leer un carcter en una posicin invlida (menor que cero o mayor o igual que la longitud de la cadena), el programa terminar con un error. Las variables de la clase String son referencias, como todos los objetos. Eso quiere decir que cuando hagamos

64S t r i n g a = "hola mundo" ; S t r i n g b = "hola mundo" ; boolean c = ( a == b ) ;

el boolean c tendr como valor false. Las variables a y b son distintas; apuntan a direcciones distintas en la memoria. Que en esas direcciones haya cadenas idnticas no le importa a Java; lo importante es que son dos referencias distintas. Si queremos comparar dos cadenas lexicogrcamente, debemos usar el mtodo equals de la clase String:c = a . equals ( b ) ;

En este caso, el valor de c s es true. Las literales de cadena en Java son objetos totalmente calicados. Por lo tanto, es posible llamar mtodos utilizndolas (por bizarro que se vea):i n t l = "hola mundo" . l e n g t h ( ) ; String b; b = "hola mundo" . s u b s t r i n g ( 0 , 4 ) ;

La clase String de Java ofrece muchas otras funciones tiles, que iremos aprendiendo a usar a lo largo de estas prcticas.

Actividad 4.5 Mediante un navegador, consulta la documentacin de la clase String. Necesitars estarla consultando para los ejercicios de esta prctica.

El recolector de basuraHemos dicho que cuando utilizamos el operador new para construir un objeto, la JVM le asigna una porcin de la memoria para que el objeto sea almacenado. Tambin dijimos que las variables de clase viven desde que el objeto es construido hasta que ste deja de existir. Y en el ejemplo de "hola mundo" dijimos que al hacerString a; a = "hola mundo" ; a = a . s u b s t r i n g ( 0 , 5 ) + "t" + a . s u b s t r i n g ( 6 , 1 0 ) ;

Interfaces y clases por dentro

65

estbamos usando tres objetos temporales (las tres subcadenas que forman "hola t undo"). Qu pasa con esas subcadenas? Cundo deja de existir un objeto? Si new hace que la JVM asigne memoria, cundo se libera esta memoria? La respuesta corta es no hay que preocuparse por ello. La larga es as: imagnense que cada objeto tiene un contador interno que se llama contador de referencias. Cuando un objeto se construye con new (aunque sea implcitamente, como las cadenas), ese contador se pone en cero. En cuanto una referencia comienza a apuntar hacia el objeto, el contador aumenta en uno. Por cada referencia distinta que empiece a apuntar hacia el objeto, el contador se aumentar en uno. Por ejemploString a; a = "cadena" ; String b , c , d , e; b = c = d = e = a;

En este ejemplo, al objeto de la clase cadena que instanciamos como adena", su contador de referencias vale 5, ya que a, b, c, d y e, apuntan hacia l. Cada vez que una referencia deje de apuntar al objeto, el contador disminuye en 1. Si ahora hacemosa = b = c = d = e = null ;

con eso las cinco referencias dejan de apuntar al objeto, y entonces su contador de referencias llega a cero. Cuando el contador de referencias llega a cero, el objeto se marca como removible. Un programa especial que corre dentro de la JVM (el recolector de basura) se encarga cada cierto tiempo de buscar objetos marcados como removibles y regresar al sistema la memoria que utilizaban. Debe quedar claro que ste es un ejemplo simplicado de cmo ocurre realmente la recoleccin de basura; en el fondo es un proceso mucho ms complejo y el algoritmo para marcar un objeto como removible es mucho ms inteligente. Pero la idea central es sa; si un objeto ya no es utilizado, que el recolector se lo lleve. La respuesta corta es suciente sin embargo. La idea del recolector de basura es que los programadores (ustedes) no se preocupen de liberar la memoria que asignan a sus objetos. En otros lenguajes eso tiene mucha importancia; mas por suerte Java lo hace por nosotros.

66

Comentarios para JavaDocNuestra interfaz MatrizCuadrada y nuestra clase Matriz2x2 estn terminadas y funcionan. Otros programadores podran querer utilizarlas para sus propios programas. Para ayudarlos a entender cmo funciona la clase, podemos hacer disponibles para ellos la documentacin generada por JavaDoc.

Actividad 4.6 Genera la documentacin de JavaDoc utilizando el objetivo docs de tu build.xml. Con la ayuda de un navegador revisa la documentacin que se genera.

Puedes ver que la documentacin generada es bastante explcita por s misma. Nos dice el tipo de regreso de los mtodos, as como sus parmetros, y qu constructores tiene la clase. Con esa informacin, cualquiera que sepa lo que nosotros sabemos hasta el momento, puede empezar a trabajar con una clase. Sin embargo, podemos hacer todava ms para que la documentacin sea an ms explcita. Podemos utilizar comentarios especiales para que JavaDoc haga la documentacin ms profunda. Para que JavaDoc reconozca que un comentario va dirigido hacia l, necesitamos comenzarlos con /* * en lugar de slo /* . Despus de eso, slo necesitamos poner el comentario inmediatamente antes de la declaracin de un mtodo, un constructor o de una clase para que JavaDoc lo reconozca. Modica as la declaracin de la claseMatriz2x2 3 4 5 6 7 8 9 /* *

* Clase para r e p r e s e n t a r m a t r i c e s de dos r e n g l o n e s * por dos columnas , que implementa l a i n t e r f a z * MatrizCuadrada . */ public class M a t r i z 2 x 2 implements MatrizCuadrada { ...

y modica as la declaracin del mtodo multiplica (el que multiplica por escalares):15 16 17 18 19 * C a l c u l a e l r e s u l t a d o de m u l t i p l i c a r l a m a t r i z por * un e s c a l a r . */ public MatrizCuadrada m u l t i p l i c a ( double x ) { /* *

Interfaces y clases por dentro20 ...

67

Vuelve a generar la documentacin de la clase y consltala para que veas los resultados. Para mtodos, podemos mejorar todava ms la documentacin utilizando unas etiquetas especiales. Vuelve a modicar el comentario del mtodo multiplica, pero ahora as:15 16 17 18 19 20 21 22 23 24 * C a l c u l a e l r e s u l t a d o de m u l t i p l i c a r l a m a t r i z por * un e s c a l a r . * @param x e l e s c a l a r por e l que se m u l t i p l i c a r la matriz . * * @return l a m a t r i z r e s u l t a n t e de m u l t i p l i c a r e s t a m a t r i z por e l e s c a l a r x . * */ public MatrizCuadrada m u l t i p l i c a ( double x ) { ... /* *

Vuelve a generar la documentacin y comprueba los cambios. La etiqueta @param le sirve a JavaDoc para saber que vamos a describir uno de los parmetros del mtodo. El nombre del parmetro debe corresponder a alguno de los parmetros que recibe el mtodo, obviamente. Si no, JavaDoc marcar un error, aunque generar la documentacin de todas maneras. La etiqueta @return le dice a JavaDoc que se va a describir qu es lo que regresa el mtodo. Todos los mtodos que escribas de ahora en adelante debern estar documentados para JavaDoc, con su valor de regreso (si no es void), y cada uno de los parmetros que reciba, si recibe. Las clases tambin tienen que estar documentadas.

EjerciciosEntre las aplicaciones ms utilizadas en el mundo de la computacin estn las bases de datos. A partir de esta prctica, iremos recolectando todo lo que aprendamos para construir poco a poco una bases de datos para una agenda. Una base de datos tiene registros, que a su vez estn compuestos de campos. Los campos de nuestra base de datos para una agenda sern nombre, direccin y telfono y cada registro representar a un individuo. Por ahora empezaremos con una base de datos ya llena, lo que quiere decir que los datos ya estn dados y que no necesitars introducirlos t mismo.

68 Aunque hay muchas formas de implementar bases de datos, una de las ms comunes es utilizar una tabla; los renglones son los registros, y las columnas campos, como en Nombre Juan Prez Garca Arturo Lpez Estrada Edgar Hernndez Levi Mara Garca Snchez Pedro Pramo Rulfo Jos Arcadio Buenda Florentino Ariza Galio Bermdez Carlos Garca Vigil Eligio Garca Agusto Direccin Avenida Siempre Viva # 40 Calle de la abundancia # 12 Oriente 110 # 14 Avenida Insurgentes Sur # 512 Avenida Mxico Lindo # 23 Macondo # 30 Calle de la Clera # 11 Stanos de Mxico # 45 La Repblica # 1 Ciudades Desiertas # 90 Telfono 55554466 55557733 55512112 56742391 54471499 56230190 55551221 55552112 55554332 56344325

Para representar a todos los datos, utilizaremos una sola variable esttica de tipo cadena, llamada tabla. Los registros (o renglones) son de tamao jo, as que si queremos el primer registro slo necesitamos hacert a b l a . s u b s t r i n g ( 0 ,TAM_REGISTRO ) ;

Donde TAM_REGISTRO es otra variable, esttica y nal, que tiene el tamao del registro. Si necesitamos el segundo registro, tenemos que hacert a b l a . s u b s t r i n g (TAM_REGISTRO, TAM_REGISTRO+TAM_REGISTRO ) ;

En general, si necesitamos el i-simo registro (donde el primer registro es el registro 0, como buenos computlogos), hacemost a b l a . s u b s t r i n g ( i * TAM_REGISTRO, i * TAM_REGISTRO+TAM_REGISTRO ) ;

o lo que es lo mismot a b l a . s u b s t r i n g ( i * TAM_REGISTRO, ( i + 1 ) * TAM_REGISTRO ) ;

Para obtener los campos se necesita algo similar usando los tamaos de cada campo. Nota que estamos usando TAM_REGISTRO solo, sin hacer this.TAM_REGISTRO o BaseDeDatosAgenda.TAM_REGISTRO. Esto es porque estamos dentro de la clase

Interfaces y clases por dentro

69

BaseDeDatosAgenda; cuando usamos TAM_REGISTRO el compilador asume que habla-

mos de las variables de la clase donde estamos. Por ahora, supondremos que todos los campos son nicos; o sea que no se repiten nombres, ni direcciones ni telfonos. 1. Por ahora, nuestra base de datos de agenda ser slo de lectura, ya que no insertaremos nuevos registros ni borraremos ninguno. Sin embargo s leeremos datos, y de hecho podremos hacer bsquedas. Abre el archivo BaseDeDatosAgenda.java donde est el esqueleto de lo que hemos estado discutiendo. Por ahora slo tiene dos funciones (vacas); dameRegistroPorNombre y dameRegistroPorTelefono. La primera recibe una cadena con el nombre a buscar y la segunda recibe un entero con el telfono. Ambas regresan una cadena, que es el registro que caza la bsqueda, o null si el nombre o telfono no estn en la base de datos. Por ejemplo, si hacemosBaseDeDatosAgenda bdda ; S t r i n g busqueda ; bdda = new BaseDeDatosAgenda ( ) ; busqueda = bdda . dameRegistroPorNombre ( "Pedro Pramo Rulfo" ) ;

Entonces la cadena busqueda debe valer"Pedro Pramo Rulfo Avenida Mxico Lindo 23 54471499"

Y lo mismo si hacemosbusqueda = bdda . dameRegistroPorTelefono ( 5 4 4 7 1 4 9 9 ) ;

Utilizando las funciones de la clase String, implementa los mtodos. Una pista para ayudar: vas a necesitar convertir enteros en cadenas. Piensa que necesitars el valor de un entero como cadena. Y vas a necesitar encontrar dnde empieza una subcadena dentro de otra cadena. Lee todos los mtodos de la clase cadena (en la documentacin generada de la clase String), antes de utilizar alguno. 2. Queremos utilizar nuestra base de datos, as que escribe una clase de uso llamada UsoBaseDeDatosAgenda, que slo tenga la funcin main y utilice las funciones que has escrito. El esqueleto de la clase est ya en el archivo UsoBaseDeDatosAge