Está en la página 1de 79

Traducido del inglés al español - www.onlinedoctranslator.

com

CAPITULO 2
---

Algunos conceptos básicos de Java

t Los objetivos de este libro no son sólo enseñarle sobre objetos y su modelado, sino también ilustrar cómo los
objetos se traducen en una aplicación de software funcional. Entonces, antes de sumergirnos en los conceptos
básicos de los objetos en el Capítulo 3, dedicaremos algún tiempo a familiarizarnos con los fundamentos de Java,
ya que este es el lenguaje de programación utilizado para ilustrar los conceptos de objetos a medida que se
presentan a lo largo del libro.
Los objetos son “neutrales al lenguaje”, por lo que lo que aprenderá conceptualmente sobre los objetos en la Parte
1 de este libro y sobre el modelado de objetos en la Parte 2, podría aplicarse igualmente bien a Java, C++, C# o un
software aún no desarrollado. -Lenguaje orientado a objetos (OO) por inventar. Elegí Java específicamente por las muchas
ventajas que este elegante lenguaje de programación OO nos brinda como desarrolladores de software, que
exploraremos en este capítulo.
En este capítulo, también aprenderá sobre

• Tipos primitivos de Java, operadores de esos tipos y expresiones formadas con esos tipos.

• La anatomía de un programa Java simple

• La mecánica de compilar y ejecutar dichos programas.

• Javaestructurado en bloquesnaturaleza

• Varios tipos de Javaexpresiones

• Bucles y otras estructuras de control de flujo

• Imprimir mensajes en la ventana de comandos desde la que se inició un programa, lo cual es


especialmente útil para probar el código a medida que evoluciona

• Elementos del estilo de programación Java.

Si es un programador competente en C, C++ o C#, encontrará que gran parte de la sintaxis de


Java le resultará muy familiar y podrá leer este capítulo con bastante rapidez.

¿Por qué Java?


Después de aprender qué hace que los objetos funcionen en la Parte 1 del libro y cómo modelar una aplicación
para aprovechar los objetos en la Parte 2, estará listo para el gran final: renderizar un modelo de objetos en
código para producir un Student funcional. Aplicación del Sistema de Registro (SRS) en la Parte 3. Como se
mencionó anteriormente,podríarecorra la construcción del SRS utilizando cualquier lenguaje de programación
OO. ¿Por qué querríamos utilizar Java? ¡Sigue leyendo y verás rápidamente por qué!

15
dieciséis CAPITULO 2-ALGUNOS BASICOS DE JAVA

Java es arquitectura neutral


Para ejecutar un programa escrito en un lenguaje compilado convencional como C o C++, el código fuente
primero debe compilarse en un formato ejecutable conocido comocódigo binarioocodigo de maquina. El código
binario, en esencia, es un patrón de unos y ceros comprensible por el código subyacente.arquitectura de
hardwaredel ordenador en el que se pretende ejecutar el programa.
Incluso si el código fuente original C o C++ está escrito para serplataforma independiente—es decir, el programa
no aprovecha ninguna extensión de lenguaje específica de la plataforma, como un tipo específico de acceso a archivos o
manipulación de la interfaz gráfica de usuario (GUI); no obstante, la versión ejecutable resultante seguirá vinculada a la
arquitectura de una plataforma en particular y puede por lo tanto, se ejecutará únicamente en esa arquitectura. Es decir,
una versión del programa compilada para una estación de trabajo Sun Solaris no se ejecutará en una PC con Windows,
una versión compilada para una PC con Windows no se ejecutará en una máquina con Linux, etc. Este concepto se
representa en la Figura 2-1.

Figura 2-1.Los lenguajes compilados convencionalmente producen programas ejecutables dependientes de la plataforma.
CAPITULO 2-ALGUNOS BASICOS DE JAVA 17

Por el contrario, el código fuente de Java no se compila para una plataforma particular, sino más bien en un
formato intermedio especial conocido comocódigo de bytes, que se dice que es independiente de la plataforma y
arquitectura neutral. Es decir, no importa si un programa Java se compila bajo Sun Solaris, Windows, Linux o
cualquier otro sistema operativo para el cual esté disponible un compilador Java, el código de bytes resultante
resulta ser el mismo y, por lo tanto, se puede ejecutar en cualquier computadora para cual (plataforma-específico
) La máquina virtual Java (JVM) está disponible. Esto se ilustra en la Figura 2-2.

Figura 2-2.El compilador de Java genera un código de bytes independiente de la plataforma.


18 CAPITULO 2-ALGUNOS BASICOS DE JAVA

La JVM es una pieza de software especial que sabe cómointerpretary ejecutar el código de bytes de Java. Es
decir, en lugar de que un programa Java se ejecute directamente bajo el control del sistema operativo como lo
hacen los programas compilados tradicionalmente, la propia JVM se ejecuta bajo el control directo del sistema
operativo y nuestro programa Java, a su vez, se ejecuta bajo el control de la JVM, como lo hacen los programas
Java. ilustrado en la Figura 2-3. En esencia, la JVM sirve como traductor, traduciendo el “lenguaje” universal de
código de bytes de Java al “lenguaje” de código de máquina que una computadora en particular puede entender,
de la misma manera que un intérprete humano facilita una discusión entre alguien que habla alemán y alguien
que habla japonés. traduciendo sus declaraciones mientras conversan.

Figura 2-3.Se utiliza una JVM dependiente de la plataforma para ejecutar código de bytes independiente de la plataforma.

La naturaleza interpretada del lenguaje Java tiende a convertirlo en undiminutoun poco más lento, en general, que los lenguajes

compilados porque hay una capa de procesamiento adicional involucrada cuando se ejecuta una aplicación, como se ilustra en la Figura

2-3. Sin embargo, para las aplicaciones de sistemas de información tradicionales que involucran a un usuario humano en el bucle, la

diferencia de velocidad es imperceptible; Otros factores, como la velocidad de la red (en el caso de aplicaciones distribuidas), la velocidad

de un servidor DBMS (si se utiliza una base de datos) y especialmente el "tiempo de reflexión" humano mientras responde a la interfaz de

usuario de una aplicación, pueden causar cualquier retraso en el tiempo de respuesta de JVM palidece en comparación.

Siempre que tenga instalada la JVM adecuada en una plataforma de destino determinada, puede transferir el
código de bytes de Java de una plataforma a otra sin volver a compilar el código fuente de Java original, y aún
podrá ejecutarse. Es decir, el código de bytes se puede transferir entre plataformas, como se ilustra en la Figura
2-4.
CAPITULO 2-ALGUNOS BASICOS DE JAVA 19

Figura 2-4.Las JVM entienden exactamente el mismo código de bytes en dos plataformas diferentes.

MIGRACIÓN DE CÓDIGO DE BYTE

Hay dos advertencias importantes a tener en cuenta al migrar código de bytes de una máquina a otra. El primero implica migrar a

través de diferentesversionesdel lenguaje Java, incluso si se encuentra en la misma plataforma. El código de bytes de Java es, en

teoría,compatible con versiones anteriorescon versiones más nuevas de JVM, lo que significa que si un programa Java se compila

con una versión del lenguaje Java (por ejemplo, la versión 1.3.1) se ejecutará correctamente en una versión más nueva de JVM (por

ejemplo, la versión 1.4.2). Sin embargo, puede haber ligeras diferencias en la forma en que se ejecuta una aplicación en una versión

más reciente de JVM, debido nada más que quizás a que se haya corregido un error menor en una versión anterior del lenguaje

Java.

Incluso al migrar a lamismoversión de Java endiferentearquitecturas de hardware, sin embargo, pueden surgir

incompatibilidades menores. Sun Microsystems es responsable de lanzar nuevas versiones de Java sólo para un puñado de

plataformas, en particular, “versiones” más nuevas de Windows, Linux y Sun Solaris (Unix). Depende de otros proveedores de

hardware proporcionar JVM compatibles para sus respectivas plataformas (por ejemplo, Apple Macintosh y SGI IRIX [Unix]). Me he

encontrado con situaciones en las que un proveedor en particular lanza una versión de Java que tiene el mismo número de versión

que una versión de Java de Sun, pero donde las características de la versión de ese proveedor no están a la altura de la versión de

Sun con un número similar.

La conclusión es que es mejor recompilar el código fuente de Java para una plataforma de destino determinada antes de

transferir el código de bytes resultante a esa plataforma, si tiene ese lujo.


20 CAPITULO 2-ALGUNOS BASICOS DE JAVA

Java proporciona una “ventanilla única”


Con la mayoría de los lenguajes de programación convencionales, el lenguaje central no proporciona
automáticamente todo lo que necesita para crear una aplicación industrial, con una GUI y acceso a un sistema de
administración de bases de datos. Para estas capacidades, normalmente debe integrar plataformas específicas (y
a menudo,proveedor-específicas) en su aplicación, como se ilustra en la Figura 2-5.

Figura 2-5.Integrar bibliotecas específicas de la plataforma en una aplicación que de otro modo sería independiente de
la plataforma

La inclusión de dichas llamadas a bibliotecas específicas de plataformas y proveedores dificulta la migración de


aplicaciones de una plataforma a otra, porque no todas las bibliotecas requieren una plataforma determinada.X
necesariamente tenerun equivalente para una plataforma de destinoY—por ejemplo, no todos los controles Microsoft
ActiveX (usados para crear GUI para computadoras con Windows) tienen un equivalente en la biblioteca Motif de
componentes GUI (usados para crear GUI para máquinas Unix), y viceversa.
Peor aún, el límite entre la plataforma-independientey plataforma-/proveedor-dependiente El código no es
realmente tan limpio como se muestra en la Figura 2-5. Las llamadas a estas bibliotecas a menudo están dispersas en
toda una aplicación, como se ilustra en la Figura 2-6, lo que hace que la tarea de migrar una aplicación de una plataforma
a otra sea, en el mejor de los casos, problemática y prohibitivamente difícil en el peor de los casos.
CAPITULO 2-ALGUNOS BASICOS DE JAVA 21

Figura 2-6.Los límites entre el código dependiente de la plataforma y el código independiente de la plataforma no están
claros.

Si el límite entre los componentes independientes y dependientes de la plataforma de una


aplicación es particularmente complicado, a veces es el menor de dos males reescribir toda la
aplicación desde cero en lugar de intentar migrarla.
Hay algunos programas especiales de terceros disponibles llamadosemuladoresque simulará un sistema
operativo bajo otro, permitiéndonos (en teoría) ejecutar una aplicación dependiente de la plataforma en otra
plataforma incompatible sin ninguna modificación. Sin embargo, no todas las aplicaciones necesariamente se
ejecutarán correctamente en un emulador, y aquellas que lo hacen normalmente funcionan con lentitud.

Por el contrario, el lenguaje Java proporciona un amplio conjunto deinterfaces de programación de aplicaciones(
API) que proporcionan una consistencia,plataforma independientemedios para acceder a todas las funciones
subyacentes del sistema operativo, incluida la representación GUI y el acceso al sistema de gestión de bases de datos
(DBMS). Cubriremos las siguientes API de Java más adelante, en la Parte 3 del libro:

• java.io:Se utiliza para acceder al sistema de archivos (consulte el Capítulo 15)

• java.sql:La API JDBC, utilizada para comunicarse con bases de datos relacionales de forma independiente
del proveedor (consulte el Capítulo 15)

• java.awt:El kit de herramientas de ventanas abstractas, utilizado para el desarrollo de GUI (consulte el Capítulo 16)

• javax.swing:Componentes Swing, también utilizados para el desarrollo de GUI (ver Capítulo 16)
22 CAPITULO 2-ALGUNOS BASICOS DE JAVA

Y aquí estánmuchos¡más! Si estas bibliotecas Java integradas se utilizan para desarrollar aplicaciones Java 100%
puras, como se ilustra en la Figura 2-7, el código Java resultante es verdaderamente portátil entre plataformas y
proveedores. Entonces, para migrar unJavaaplicación de Windows XP a Linux, por ejemplo, no es necesario
arrancar el código (¡ni tu cabello!): simplemente transfiere el código de bytes de la aplicación a la nueva
plataforma, y siempre que la nueva plataforma host tenga la versión apropiada de una plataforma específica
JVM instalado, entonces estará listo para comenzar.

Figura 2-7.Una aplicación Java 100% pura es independiente de la plataforma, desde GUI hasta DBMS.

En la parte 3 del libro, discutiremos dosde importancia críticatécnicas de diseño—separación de capas de acceso a datos

modeloyseparación modelo-vista—Lo que garantizará aún más la flexibilidad de proveedores y plataformas de nuestras

aplicaciones.

Java está orientado a objetos desde cero


Antes de que aparecieran en escena los lenguajes OO más nuevos como Java, uno de los lenguajes OO más utilizados
era C++, que en realidad es una extensión orientada a objetos del lenguaje C que no es OO. Como tal, C++ proporciona
muchas "puertas traseras" que hacen que sea muy fácil escribir código decididamente no-OO. De hecho, muchos
programadores competentes en C hicieron la transición a C++ como un mejor C sin aprender adecuadamente cómo
diseñar una aplicación OO y, por lo tanto, terminaron usando C++ en su mayor parte como un lenguaje de
procedimientos (no OO).

Si es un programador experimentado en C++ y desea saber más sobre las diferencias entre C++ y
Java, consulte el Apéndice E.

Por el contrario, Java está orientado a objetos hasta su esencia. Como aprenderá con más
detalle en los capítulos siguientes, casitodoen Java es un objeto:

• Todos los datos, con excepción de unos pocos tipos primitivos, se representan como objetos.

• Todos los componentes básicos de la GUI (ventanas, botones, campos de entrada de texto, barras de
desplazamiento, listas, menús, etc.) son objetos.
CAPITULO 2-ALGUNOS BASICOS DE JAVA 23

• Todas las funciones están asociadas con objetos y se conocen comométodos—No puede haber
funciones “flotantes” como las que hay en C/C++.

• Incluso la función principal utilizada para iniciar una aplicación (en Java se llamamétodo principal) ya
no está solo, sino que está incluido dentro de unclase, cuyas razones exploraremos en profundidad
en los próximos capítulos.

Debido a esto, Java se presta particularmente bien para escribir aplicaciones que mantengan el
paradigma OO. Sin embargo, como señalé en la introducción de este libro, el mero uso de dicho lenguaje
OO no significagarantizarque las aplicaciones que usted produzca seránverdaderoa este paradigma! Debe
tener conocimientos sobre cómo diseñar una aplicación desde cero para hacer el mejor uso de los objetos y
cómo aplicar el lenguaje correctamente, que son los objetivos principales de este libro.

La práctica hace la perfección


Los diseñadores del lenguaje Java de Sun Microsystems pudieron aprovechar las lecciones aprendidas de otros lenguajes
de programación OO que lo precedieron. Tomaron prestadas las mejores características de C++, Eiffel, Ada y Smalltalk, y
luego agregaron algunas capacidades y características que no se encuentran en esos lenguajes. Por el contrario, se
eliminaron las características que habían demostrado ser más problemáticas en esos lenguajes anteriores.

Además, a partir de la versión 5.0 (también conocida como 1.5) de Java, varias características de unmás nuevoEl lenguaje C# de

Microsoft se adaptó a Java.

Esto no quiere decir que Java sea un lenguaje “perfecto” (¡ningún lenguaje lo es!), sino simplemente que ha
realizado algunas mejoras significativas con respecto a muchos de los lenguajes que lo precedieron.

Java es un estándar abierto


¿Qué importancia tiene para nosotros como desarrolladores de software el hecho de que Java sea un estándar abierto? Por un
lado, todo el código fuente detrás de todas las bibliotecas Java integradas está disponible para que lo estudiemos y lo utilicemos
como base para nuestro propio diseño de software.
Además, la industria de TI en su conjunto se ha apresurado a adoptar Java porque no se ha excluido a
ningún proveedor externo, como suele ocurrir con una tecnología propietaria/“cerrada”. Todo lo contrario:
Sun Microsystems ha alentado a otros proveedores a adoptar el estándar Java e incorporar capacidades
Java en sus productos, permitiéndoles participar en el avance de las especificaciones de la tecnología Java a
través del estándar de Sun.Proceso de la comunidad Java.
Y si las razones anteriores aún no son lo suficientemente convincentes como para convencerlo de los méritos de
Java. . .

¡Java es gratis!
Sun Microsystems se ha asegurado de que Java disfrute de una adopción generalizada, en parte, al crear el
lenguaje y todas las herramientas básicas necesarias para desarrollar aplicaciones Java.gratis! El Apéndice C
proporciona información sobre lo que deberá hacer para descargar elKit de desarrollo de software Java 2(SDK)
del sitio web de Sun (http://java.sun.com)para comenzar con el desarrollo de Java. (Proporciono instrucciones
sobre cómo compilar y ejecutar programas Java un poco más adelante en este capítulo).
El resto de este capítulo presenta cierta sintaxis elemental de Java, que continuaremos
desarrollando en capítulos posteriores.
24 CAPITULO 2-ALGUNOS BASICOS DE JAVA

Un recordatorio sobre el pseudocódigo frente al código Java real


De vez en cuando utilizo pequeños fragmentos de pseudocódigo en los ejemplos de código de las Partes 1 y 2 de
este libro para ocultar detalles lógicos irrelevantes. Para dejar claro cuándo estoy usando pseudocódigo en lugar
de código real, usoitálicoen vez defuente condensada SansMono normal.
Esta es la sintaxis real de Java:

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

Este es un pseudocódigo:

calcular la calificación para el i-ésimo estudiante


}
Te recordaré este hecho unas cuantas veces más, para que no lo olvides y accidentalmente intentes
escribir y compilar pseudocódigo en algún momento del camino.

Anatomía de un programa Java simple


La Figura 2-8 muestra una de las aplicaciones Java más simples.

Figura 2-8.Anatomía de un programa Java simple

Repasemos los elementos clave de nuestro sencillo programa.

Comentarios
Lo primero que vemos en nuestro sencillo programa Java es un comentario introductorio:

// Este sencillo programa ilustra algo de sintaxis básica de Java.

Java admite tres estilos de comentarios diferentes: comentarios tradicionales, de final de línea y de
documentación de Java.
CAPITULO 2-ALGUNOS BASICOS DE JAVA 25

Comentarios tradicionales

Javacomentarios tradicionalesderivan del lenguaje C y comienzan con una barra diagonal seguida de un
asterisco (/*) y terminan con un asterisco seguido de una barra diagonal (*/). Todo lo incluido entre estos
delimitadores se trata como un comentario y, por lo tanto, el compilador de Java lo ignora, sin importar
cuántas líneas abarque el comentario.

/* Este es un comentario tradicional (estilo C). */

/* Este es un comentario tradicional de varias líneas. Esta es una manera práctica de temporalmente
comente secciones enteras de código sin tener que eliminarlas. Desde el momento en que
el compilador encuentra el primer "asterisco diagonal" arriba, no le importa lo que
escribamos aquí; Incluso las líneas de código legítimas, como se muestra a continuación, se
tratan como líneas de comentarios y, por lo tanto, el compilador las ignora hasta que se
encuentra la primera combinación de "barra asterisco".
x = y + z;
a = b/c;
j = s + c + f;
*/

/* A menudo utilizamos asteriscos iniciales desde la segunda hasta la última línea de un tradicional
*comentar simplemente por motivos estéticos, para que el comentario sea más visual
* distinto; pero estos asteriscos adicionales son estrictamente cosméticos: solo el
* La "barra asterisco" inicial y la "barra asterisco" final están indicadas por el
* compilador por tener algún significado.
*/

Tenga en cuenta que no podemosnidobloquear comentarios, es decir, lo siguientenocompilar:

/* Esto inicia un comentario ... x


= 3;
/* ¡Vaya! ¡Estamos intentando por error anidar un SEGUNDO comentario
antes de cancelar el PRIMERO!
Esto nos va a causar problemas de compilación, porque el
El compilador va a IGNORAR el comienzo de este segundo comentario interno. ¡Después de
todo, ya estamos EN un comentario! -- y tan pronto como intentemos terminar este
SEGUNDO comentario interno, el compilador pensará que hemos terminado el PRIMER
comentario externo... */
z = 2;
// El compilador se "quejará" en la siguiente línea.
*/

Cuando el compilador llegue a lo que pretendíamos que fuera el final */ del comentario "externo" en la
última línea del ejemplo de código anterior, se informarán los dos errores de compilación siguientes:

inicio ilegal de expresión


*/
^
26 CAPITULO 2-ALGUNOS BASICOS DE JAVA

';' esperado
*/
^

Comentarios de fin de línea

El segundo tipo de comentario de Java deriva de C++ y se conoce comocomentario de fin de línea. Usamos una
doble barra (//) para anotar el comienzo de un comentario que termina automáticamente cuando se llega al final
de la línea, como se muestra aquí:

x = y + z; // el texto del comentario continúa hasta el final de la línea ==>


a = b/c;

// Aquí hay un BLOQUE de comentarios secuenciales de final de línea.


// Esto sirve como una alternativa al uso de comentarios tradicionales // (/
* ... */) y es el preferido por muchos programadores de Java.

metro = norte * p;

Comentarios sobre la documentación de Java

El tercer y último tipo de comentario Java,Comentarios de la documentación de Java(aliascomentarios javadoc), se


puede analizar a partir de archivos de código fuente mediante un programa especialjavadocprograma de utilidad de
línea de comandos (que viene de serie con el SDK de Java) y se utiliza para generar automáticamente documentación
HTML para una aplicación.
Aplazaremos una mirada en profundidad a los comentarios de Javadoc hasta el Capítulo 13.

La declaración de clase
Luego viene uncontenedor de clase—más propiamente denominado undeclaración de clase-de la forma

clase públicaNombre de la clase{


...
}

Por ejemplo:

clase pública Programa Simple {


...
}

donde llaves {...} encierran elcuerpo de claseque incluye la lógica principal del programa junto con otros
bloques de construcción opcionales de una clase.
En los capítulos siguientes, aprenderá todo sobre la importancia de las clases en un lenguaje de
programación OO. Por ahora, simplemente tenga en cuenta que los símbolospúblicoyclaseson dos de Java
palabras clave—es decir, símbolos reservados para usos específicos dentro del lenguaje Java—mientras que
Programa simplees un nombre/símbolo que he inventado.
CAPITULO 2-ALGUNOS BASICOS DE JAVA 27

El método principal
Dentro dePrograma simpledeclaración de clase, encontramos el punto de partida para el programa, llamado
método principalen Java. ElprincipalEl método sirve como punto de entrada para un programa Java. Cuando
ejecutamos un programa Java interpretando su código de bytes con una instancia de la JVM, la JVM llama al
principalmétodo para iniciar nuestra aplicación.

Con aplicaciones triviales como laPrograma simplePor ejemplo, toda la lógica del programa puede estar contenida
dentro de este únicoprincipalmétodo. Por otro lado, para aplicaciones más complejas, elprincipalEl método no puede
contener toda la lógica de todo el sistema. Aprenderá cómo construir una aplicación que trascienda los límites del
principalmétodo, que involucra múltiples archivos de código fuente Java, un poco más adelante en el libro.

La primera línea del método, que se muestra aquí.

público estático vacío principal (String [] argumentos) {

define lo que se conoce comoprincipalmétodosencabezado del métodoy debe aparecer exactamente como se muestra
(con una excepción menor que explicaré en el Capítulo 13 y que tiene que ver con la recepción opcional de argumentos
desde la línea de comando).
Nuestroprincipalmétodoscuerpo del método, encerrado entre llaves {...}, consta de una sola declaración:

System.out.println("¡Hola!");

que imprime el mensaje

¡Hola!

a la ventana de comandos (DOS/Solaris/Linux) desde la que se inicia nuestro programa. Examinaremos la sintaxis
de esta declaración más adelante, pero por ahora, tenga en cuenta el uso de un punto y coma (;) al final de la
declaración. Al igual que en C y C++, el punto y coma se colocan al final de todas las declaraciones individuales de
Java. Las llaves {...}, a su vez, delimitanbloquesde código, cuyo significado analizaré con más detalle más adelante
en este capítulo.
Otras cosas que normalmente haríamos dentro delprincipalEl método de un programa más
elaborado incluye declarar variables, crear objetos y llamar a otros métodos.
Ahora que hemos visto la anatomía de un programa Java simple, analicemos cómo se
compila y ejecuta dicho programa.

Consulte el Apéndice C para obtener detalles sobre cómo instalar correctamente el kit de desarrollo de software (SDK) Java

2 en su computadora antes de continuar.


28 CAPITULO 2-ALGUNOS BASICOS DE JAVA

La “mecánica” de Java
Una vez que hayamos ingresado la lógica de nuestro programa, como texto, en un archivo, usando un editor de texto
simple (como el Bloc de notas de Windows o vi) o una herramienta de entorno de desarrollo integrado (IDE) de Java,
primero debemos compilar el código fuente en código de bytes antes de podemos ejecutarlo.

Para las personas que recién comienzan a programar en Java, recomiendo usar un editor de texto simple al principio para que no

se distraigan con las comodidades de un IDE específico y para que el IDE no haga tanto trabajo por ustedes. realmente no

aprendes lo que está pasando en el nivel más básico. Sin embargo, si le gusta trabajar con IDE, le recomiendo comenzar con una

herramienta muy económica llamadaPad de texto, disponible enhttp://www.textpad.com.

Para las personas que dominan vi (un editor de Unix/Linux), tengan en cuenta que existe una versión
compatible con Windows/DOS llamadaempujeque está disponible sin costo desdehttp://www.vim.org—
específicamente, se puede descargar desdehttp://www.vim.org/download.php.
Una vez que haya dominado el lenguaje Java, puede "graduarse" a un IDE más complejo si lo desea.

La forma más sencilla de compilar y ejecutar un programa Java es mediante comandos de línea de comandos, que
son los mismos ya sea que estemos desarrollando en una computadora Sun Solaris, Linux o Windows.

USO DEL INDICADOR DE COMANDO

En el caso de Windows, abra unSímbolo del sistemaventana seleccionando el menú Inicio - Ejecutar, luego escribacmd en el cuadro de

diálogo que aparece, como se muestra en la siguiente imagen; luego haga clic en Aceptar.
CAPITULO 2-ALGUNOS BASICOS DE JAVA 29

En la siguiente imagen se muestra una ventana de símbolo del sistema de muestra.

Para ampliar la capacidad de la ventana del símbolo del sistema y/o cambiar su tamaño, haga clic derecho en la barra de encabezado

azul de la ventana y elija Propiedades en el menú emergente que aparece, como se muestra en la siguiente imagen.
30 CAPITULO 2-ALGUNOS BASICOS DE JAVA

En el panel Diseño del cuadro de diálogo que aparece (como se muestra en la siguiente imagen para una computadora con

Windows XP), ajuste las opciones Tamaño del búfer de pantalla y Tamaño de ventana como se indica.

Compilación del código fuente de Java en código de bytes


Para compilar el código fuente de Java desde la línea de comandos, utilizamos elcdcomando, según sea necesario,
para navegar al directorio de trabajo donde reside nuestro código fuente. Luego escribimos el siguiente
comando:

javaccódigo fuente_nombre de archivo

Por ejemplo:

javacProgramaSimple.java

para compilarlo.
Si hubiera más de uno.Javaarchivo de código fuente en el mismo directorio, podríamos enumerar
los nombres de los archivos a compilar, separados por espacios:

javac Foo.java Bar.java Otro.java

o utilice el carácter comodín (*), por ejemplo:

javac*.java

para compilar varios archivos al mismo tiempo.


CAPITULO 2-ALGUNOS BASICOS DE JAVA 31

Si todo va bien, es decir, si no surgen errores del compilador, entonces se creará un archivo de código de bytes con
el nombre de Clase de programa simpleaparecerá en el mismo directorio dondeProgramaSimple.javareside el archivo
de código fuente. Por otro lado, si surgen errores del compilador, por supuesto debemos corregir nuestro código fuente
e intentar recompilarlo.
Consulte la sección titulada "Errores de compilación comunes" en el Apéndice C para obtener una
lista de algunos de los errores de compilación comunes y cómo resolverlos.

Ejecutando código de bytes


Una vez que un programa se ha compilado exitosamente, ejecutamos la versión del código de bytes mediante el
comando

Javabytecode_nombredearchivo (tenga en cuenta que OMITIMOS el sufijo .class)

Por ejemplo:

programa simple java

Tenga en cuenta que es importanteomitirel .clasesufijo del nombre del archivo de código de bytes (que se llama
Clase de programa simpleen este caso).
De forma predeterminada, la JVM buscará dichos archivos de código de bytes en su directorio de trabajo
predeterminado junto con el directorio "inicio" donde se instaló el lenguaje Java en su sistema informático. Si la
JVM encuentra el archivo de código de bytes especificado, ejecuta suprincipalmétodo, ¡y su programa estará listo
y funcionando!
Si por alguna razón el código de bytes que está intentando ejecutar no se encuentra en ninguna de estas dos
ubicaciones predeterminadas, debe informar a la JVM sobre directorios adicionales en los que buscar. Puede hacerlo
especificando una lista de directorios (separados por punto y coma [;] en Windows, o por dos puntos [:] en Solaris y
Linux) después de -CPbandera en elJavacomando de la siguiente manera:

java-cplista_de_nombres_directorios_que_se_buscarán código_byte_nombre_archivo

Por ejemplo, en DOS/Windows:

java –cp C:\home\javastuff;D:\reference\workingdir;S:\foo\bar\files Programa Simple

o en Solaris/Linux:

java –cp /barkerj/work:/java/examples/ex1 Programa Simple

Como mínimo, normalmente queremos que la JVM busque en nuestrodirectorio de trabajo actualpara archivos
de código de bytes. Con la versión 1.4.x de Java ymás tarde, esto sucede automáticamente, como se analizó
anteriormente; para las versiones 1.3.x de Java ymás temprano, debemos especificar explícitamente un único punto (.),
que es la abreviatura (DOS/Linux/Solaris) de “el directorio de trabajo actual”, como entrada de classpath; por ejemplo,
para DOS/Windows:

java-cp. Programa simple

java –cp .;C:\home\javastuff;D:\reference\workingdir Programa Simple

Consulte la sección titulada "Errores comunes de tiempo de ejecución" en el Apéndice C para obtener una lista de
algunos errores comunes de tiempo de ejecución y cómo resolverlos.
32 CAPITULO 2-ALGUNOS BASICOS DE JAVA

Una mirada entre bastidores a la JVM


Echemos un vistazo más profundo a lo que realmente sucede detrás de escena cuando escribimos el
comando.

programa simple java

para ejecutar nuestro programa.

• ElJavaEl comando hace que se inicie la JVM. Recuerde de una discusión anterior en este capítulo
que la JVM es un intérprete de código de bytes.

• La JVM a su vez busca el archivo de código de bytes que hemos nombrado en el comando
(ClaseProgramaSimpleen este caso), buscando los directorios enumerados por –CP bandera, si se
proporciona, o en el directorio de trabajo predeterminado si:CPno se utiliza.

• Suponiendo que la JVM realmente encuentra el archivo de código de bytes apropiado, carga el código de bytes en
su memoria (conceptualmente, el código de bytes sirve como un “complemento” para la JVM).

• A continuación, la JVM busca en el código de bytes que acaba de cargar la presencia del código oficial.
principalencabezado del método. Si se encuentra este método, la JVM lo ejecuta y nuestro programa
estará listo y ejecutándose.

Ahora que hemos visto la mecánica de compilar y ejecutar programas Java, exploremos algunas
de las características de sintaxis básicas de Java con más detalle.

tipos primitivos
Se dice que Java es unfuertemente tipadolenguaje de programación, en el que cuando se declara una variable,
también se debe declarar su tipo. Entre otras cosas, declarar el tipo de una variable le dice al compilador cuánta
memoria asignar para la variable en tiempo de ejecución y también limita los contextos en los que esa variable
puede usarse posteriormente en nuestro programa.
El lenguaje Java define ochotipos primitivos(los ocho nombres de estos tipos son palabras clave de Java), como se
muestra a continuación.
cuatro tipos deenteroDatos numéricos:

• byte:Entero sin signo de 8 bits

• corto:entero con signo de 16 bits

• En t:entero de 32 bits con signo

• largo:Entero con signo de 64 bits

Dospunto flotantetipos numéricos:

• flotar:Punto flotante de precisión simple de 32 bits

• doble:Punto flotante de doble precisión de 64 bits

Más dos tipos primitivos adicionales:


CAPITULO 2-ALGUNOS BASICOS DE JAVA 33

• carbonizarse:Un único carácter, almacenado utilizando codificación Unicode de 16 bits (frente a la codificación
ASCII de 8 bits), que permite a Java manejar una amplia gama de conjuntos de caracteres internacionales.

• booleano:Una variable que sólo puede asumir uno de dos valores:verdaderooFALSO (ambos valores son
palabras reservadas en Java). Las variables booleanas se utilizan a menudo como indicadores para indicar
si algún código debe ejecutarse condicionalmente o no, como en el siguiente fragmento de código:

error booleano = falso; // Inicializa la bandera. //...

// Más adelante en el programa (pseudocódigo): if


(surge alguna situación de error) {
// Establece el indicador en verdadero para indicar que se ha producido un error. error
= verdadero;
}
//...

// Aún más adelante en el programa: //


Prueba el valor de la bandera. si
(error == verdadero) {
// Pseudocódigo.
tomar acción correctiva ...
}

Hablaremos específicamente sobre la sintaxis delsideclaración, uno de varios tipos diferentes de declaraciones de
control de flujo de Java, un poco más adelante en este capítulo.

Un recordatorio importante: Si desea intentar compilar cualquiera de los fragmentos de código Java que encontrará a
lo largo del libro, recuerde que (a) pseudocódigo (cursiva) no se compilará, y (b) todo el código debe, como mínimo,
estar encerrado dentro de unprincipalmétodo, que a su vez debe estar encerrado dentro de unclasedeclaración, como se
ilustra en la Figura 2-8.

variables
Antes de que una variable pueda usarse en un programa Java, el tipo y nombre de la variable deben ser
declaradoal compilador de Java, por ejemplo:

recuento int;

La asignación de un valor a una variable se logra mediante el uso de Java.operador de asignación, =. Una
declaración de asignación consta de un nombre de variable (previamente declarado) a la izquierda de =, y una
expresión que se evalúa como el tipo apropiado a la derecha de = (cubriremos varios tipos de expresiones Java
más adelante en el capítulo). Por ejemplo:
34 CAPITULO 2-ALGUNOS BASICOS DE JAVA

recuento int = 1;

total = total + 4,0; // Aquí, asumimos que total fue declarado como una // variable
doble anteriormente en el programa.

precio = costo + (a + b)/longitud; // Una vez más asumimos que todas las variables // fueron
declaradas correctamente anteriormente en el programa.

Se puede proporcionar un valor inicial cuando se declara una variable por primera vez:

recuento int = 3;

o se puede declarar una variable en una declaración y luego asignarle un valor en una declaración separada más
adelante en el programa:

doble total;
// código intermedio... detalles omitidos
total = total + 4.0;

Se puede asignar un valor a unbooleanovariable utilizando elverdaderooFALSOliterales:

booleano terminado;
//...
terminado = verdadero;

Se puede asignar un valor literal a una variable de tipocarbonizarseencerrando el valor (un


solo carácter Unicode) ensolterocitas:

carácter c = 'A';

El uso dedoblelas comillas ("...") están reservadas para asignar valores literales aCadenavariables, un tipo distinto que se analiza

más adelante en este capítulo. Lo siguiente no se compilaría en Java:

carácter c = "A"; // Debemos usar comillas simples al asignar valores a las variables char.

Convenciones de nomenclatura de variables

Cuando se habla de nombres de variables Java, hay dos aspectos a considerar:

• En primer lugar, ¿se considera que un nombre en particularválidopor el compilador de Java?

• En segundo lugar, ¿alguna persona en particularválidonombre adherirse al nombreconvenciónque ha sido


adoptado por la comunidad de programación OO en todos los lenguajes?

VálidoLos nombres de variables en Java deben comenzar con un carácter alfabético, un guión bajo o un
signo de dólar (cuyo uso no se recomienda, ya que lo utiliza el compilador al generar código) y pueden contener
cualquiera de estos caracteres más dígitos numéricos. No se permiten otros caracteres en los nombres de
variables.
CAPITULO 2-ALGUNOS BASICOS DE JAVA 35

Los siguientes son todos nombres de variables válidos en Java:

ent simple; // comienza con carácter alfabético //


int _bajo; comienza con guión bajo
int más$dinero_es_2mucho; // puede contener signos de dólar y/o guiones bajos y/o //
dígitos y/o caracteres alfabéticos

mientras que estos no son válidos:

int 1malo; // carácter inicial inapropiado //


int número#signo; contiene un carácter no válido // lo
int fo-bar; mismo
int signo más+; // lo mismo
intx@y; // lo mismo
int notación de puntos; // lo mismo

Dicho esto, elconvenciónLo que se observa en toda la comunidad de programación OO es formar


nombres de variables usando principalmente caracteres alfabéticos, evitando el uso de guiones bajos, y
además adherirse a un estilo conocido comotripa de camello. Con carcasa camel, la primera letra del
nombre de una variable está enminúsculas, elprimeroLa letra de cada palabra concatenada subsiguiente
en el nombre de la variable está enmayúscula, y el resto de los personajes están enminúsculas. Todos los
siguientes nombres de variables son válidos y convencionales:

grado internacional;

doble calificación promedio;


Cadena miPetRat;
booleano estamos terminados;

Recuerde que, como se mencionó anteriormente, las palabras clave de Java no se pueden usar como nombres de variables. Lo

siguiente no se compilará, porquepúblicoes una palabra clave de Java:

público internacional;

De hecho, el compilador generaría lo siguientedoserror de mensajes:

no es una declaración
público internacional;

';' esperado
público internacional;

Inicialización de variables
En Java, a las variables no necesariamente se les asigna un valor inicial cuando se declaran, pero todas las
variablesdebese le asignará un valor antes de que se determine el valor de la variable.usadoen una declaración
de asignación. Por ejemplo, en el siguiente fragmento de código, dosEn t(eger) se declaran variables; un valor
inicial se asigna explícitamente a la variablefoo,pero no a variablebar.Un intento posterior de sumar los valores
de las dos variables da como resultado un error del compilador:
36 CAPITULO 2-ALGUNOS BASICOS DE JAVA

intfoo;
barra interna;

// Estamos inicializando explícitamente foo, pero no bar.


foo = 3;
foo = foo + barra; // Esta línea no se compilará.

El siguiente error del compilador surgiría en la última línea de código:

Es posible que la barra variable no se haya


inicializado foo = foo + bar;
^

Para corregir este error, necesitaríamos asignar un valor explícito abar,así comofoo,antes de
usarlos en la expresión de suma:

intfoo;
barra interna;

foo = 3;
// Ahora estamos inicializando AMBAS variables explícitamente.
barra = 7;
foo = foo + barra; // Esta línea ahora se compilará correctamente.

En el Capítulo 13 aprenderá que las reglas de inicialización automática son algo diferentes cuando se trata del
"funcionamiento interno" de los objetos.

El tipo de cadena
Veremos un tipo de Java más importante en este capítulo: elCadenatipo. ACadenarepresenta una
secuencia de cero o más caracteres Unicode.
El símboloCadenacomienza con “S” mayúscula, mientras que los nombres de los tipos primitivos se
expresan completamente en minúsculas:int, flotante, booleano,etc. Esta diferencia de capitalización es
deliberada y obligatoria:cadena (minúsculas) no funcionará como un tipo:

cadena s = "foo"; // Esto no se compilará.

Aquí está el mensaje de error:

no puedo encontrar el símbolo

símbolo: cadena

(Explicaré el significado de la capitalización deCadenacomo tipo a su debido tiempo.)


Hay varias maneras de crear e inicializar unCadenavariable. La forma más sencilla y más utilizada es
declarar una variable de tipoCadenay asignar un valor a la variable mediante unliteral de cadena. Un
literal de cadena es cualquier texto encerrado endoblecomillas, incluso si consta sólo de unacarácter
único:
CAPITULO 2-ALGUNOS BASICOS DE JAVA 37

Nombre de cadena = "Steve"; // Tenga en cuenta el uso de comillas dobles,


Cadena cadena corta = "A"; independientemente de // la longitud, cuando asignamos un
valor literal // a una variable de cadena.

Dos enfoques comúnmente utilizados para inicializar unCadenavariable con un valor de marcador de posición
temporal son los siguientes:

• Asignar una cadena vacía, representada por dos comillas dobles consecutivas:

Cadena s = "";

• Asignar el valornulo,que es una palabra clave de Java que se utiliza para indicar que unCadenaaún no se le
ha asignado un valor "real" (como aprenderá más adelante en el libro, usaremos elnulo palabra clave de
la misma manera para referencias de objetos en general):

Cadena s = nula;

El operador de signo más (+) normalmente se usa para la suma aritmética, pero cuando se usa junto
conCadenas, representaconcatenación de cadenas. Cualquier numero deCadenaLos valores se pueden
concatenar con el operador +, como lo ilustra el siguiente fragmento de código:

Cadena x = "foo"; Cadena


y = "barra"; Cadena z = x +
y + "!"; // z asume el valor "foobar!" (Los valores de x e y // no se ven
afectados)

Aprenderá sobre algunas de las muchas otras operaciones que se pueden realizar con o sobre Cadenas,
junto con información sobre su naturaleza OO, en el Capítulo 13.

Sensibilidad a mayúsculas y minúsculas

Java es undistingue mayúsculas y minúsculasidioma. Es decir, el uso de mayúsculas versus minúsculas en Java es
deliberado y obligatorio, por ejemplo:

• Los nombres de variables que se escriben de la misma manera pero que difieren en el uso de mayúsculas y minúsculas

representan diferentevariables:

// Estas son dos variables DIFERENTES en lo que respecta al compilador


de Java //.
intx; // minúsculas
entero X; // mayúsculas

• Todas las palabras clave se muestran en minúsculas:público, clase, int, booleano,Etcétera.No seas
“creativo” al capitalizar estos, ya que el compilador objetará violentamente, a menudo con
mensajes de error de compilación ininteligibles, como en el siguiente ejemplo, donde la palabra
reservadaparaestá mal capitalizado:

// La palabra reservada 'para' debe estar en


minúscula. Para (int i = 0; i < 3; i++) {

lo que a su vez produce el siguiente error de compilación aparentemente extraño:


38 CAPITULO 2-ALGUNOS BASICOS DE JAVA

'.clase' esperada
Para (int i = 0; i < 3; i++) {
^

• El nombre deprincipalEl método está en minúsculas.

• Como se mencionó anteriormente, elCadenaEl tipo comienza con una “S” mayúscula.

Expresiones Java
Java es unlenguaje orientado a la expresión. Aexpresión sencillaen Java es

• Una constante:7, falso

• Acarbonizarse(acter) literal entre comillas simples: 'A', '3'

• ACadenaliteral entre comillas dobles: "foo", "Java"

• El nombre de cualquier variable declarada correctamente:miCadena, x

• Cualquierdosde los tipos de expresión anteriores que se combinan con uno de los Java
operadores binarios(discutido en detalle más adelante en este capítulo):x + 2

• Cualquierunode los tipos de expresión anteriores que es modificado por uno de los Javaoperadores
unarios(discutido en detalle más adelante en este capítulo):yo ++

• Cualquiera de los tipos de expresión anteriores encerrados entre paréntesis: (x+2)

además de algunos tipos más de expresión relacionados con objetos que aprenderá más adelante en el
libro.
Se pueden ensamblar expresiones de complejidad arbitraria a partir de distintos tipos de
expresiones simples anidando paréntesis, por ejemplo: ((((4/x) + y) * 7) + z).

Operadores aritméticos
El lenguaje Java proporciona varios operadores aritméticos básicos, como se muestra en la Tabla 2-1.

Tabla 2-1.Operadores aritméticos de Java

Operador Descripción

+ Suma
- Sustracción
* Multiplicación
/ División
% Resto (el resto cuando el operando a la izquierda del operador % se divide por el
operando a la derecha; por ejemplo,10 % 3 = 1,porque 3 cabe en 10 tres veces,
dejando un resto de 1)

Los operadores + y - también se pueden utilizar como operadores unarios para indicar números positivos o
negativos: -3,7, +42.
CAPITULO 2-ALGUNOS BASICOS DE JAVA 39

Además del operador de asignación simple, =, existen varios operadores especializados.operadores de


asignación compuesta, que combinan la asignación de variables con una operación aritmética, como se muestra
en la Tabla 2-2.

Tabla 2-2.Operadores de asignación compuesta de Java

Operador Descripción

+= a += bes equivalente aa = a + b. a-
-= = bes equivalente aa = a-b. a *= b
*= es equivalente aa = a * b. a/= bes
/= equivalente aa = a/b. un%=bes
%= equivalente aa = a % b.

Los dos últimos operadores aritméticos que veremos son elincremento unario(++)y decremento(--)
operadores, que se utilizan para aumentar o disminuir el valor de unEn tvariable por 1 o de punto flotante (
flotador, doble)valor en 1,0. Se conocen como operadores unarios porque se aplican a una sola variable,
mientras que los operadores binarios combinan los valores de dos expresiones como se analizó
anteriormente.
Los operadores unarios de incremento y decremento también se pueden aplicar acarbonizarsevariables para
avanzar o retroceder una posición de carácter en la secuencia de clasificación Unicode. Por ejemplo, en el
siguiente fragmento de código, el valor de la variableCse incrementará desde 'mi'a 'F':

carácter c = 'e';
c++; // c se incrementará de 'e' a 'f'.

Los operadores de incremento y decremento se pueden utilizar en unprefijoosufijomanera. Si el


operador está colocadoantesla variable en la que está operando (prefijomodo), el incremento o
decremento de esa variable se realizaantesla variableactualizadoEl valor se utiliza en cualquier asignación
realizada a través de esa declaración. Por ejemplo, considere el siguiente fragmento de código, que utiliza el
operador de incremento de prefijo (++). Asumir queaybhaber sido declarado previamente comoEn t
variables en nuestro programa:

a = 1;
b = ++a;

Después de que se hayan ejecutado las líneas de código anteriores, el valor de la variableaserá 2, al
igual que el valor de la variableb.Esto se debe a que, en la segunda línea de código, el incremento de la
variablea (de 1 a 2) ocurreantesEl valor dease asigna a la variableb.Así, la única línea de código

b = ++a;

es lógicamente equivalente a lo siguientedoslíneas de código:

un = un + 1; // Incrementa primero el valor de


segundo = a; a... // ... LUEGO usa su valor.

Por otro lado, si se coloca el operador de incremento/decrementodespuésla variable en la que está


operando (sufijomodo), el incremento o decremento ocurredespuésla variableoriginal El valor se utiliza
en cualquier asignación realizada a través de esa declaración. Veamos el mismo fragmento de código con
el operador de incremento escrito en unsufijomanera:
40 CAPITULO 2-ALGUNOS BASICOS DE JAVA

a = 1;
b = a++;

Después de que se hayan ejecutado las líneas de código anteriores, el valor de la variablebserá 1,
mientras que el valor de la variableaserá 2. Esto se debe a que, en la segunda línea de código, el
incremento de la variablea (de 1 a 2) ocurredespuésEl valor dease asigna a la variableb.Así, la única línea
de código

b = a++;

es lógicamente equivalente a lo siguientedoslíneas de código:

segundo = a; // Utilice el valor de a primero... // ...


un = un + 1; LUEGO incremente su valor.

Aquí hay un ejemplo un poco más complejo; lea el comentario adjunto para asegurarse de
que puede ver cómoXacabará asignándole el valor 10:

int y = 2;
int z = 4;
int x = y++ * ++z; // a x se le asignará el valor 10, porque z se // incrementará de 4 a
5 ANTES de que su valor se use en la // expresión de multiplicación,
mientras que y permanecerá en 2 hasta // DESPUÉS de que su valor
se use en la multiplicación expresión.

Como verá más adelante, los operadores de incremento y decremento se usan comúnmente
junto con bucles.

Operadores relacionales y lógicos


Aexpresión lógicacompara dos expresiones (simples o complejas)exp1yexp2de manera específica,
resolviendo a unbooleanovalor deverdaderooFALSO.
Para crear expresiones lógicas, Java proporciona laoperadores relacionalesse muestra en la Tabla 2-3.

Tabla 2-3.Operadores relacionales de Java

Operador Descripción

exp1==exp2 verdaderosiexp1es igualexp2(tenga en cuenta el uso de undoblesigno igual para probar la igualdad).

exp1>exp2 verdaderosiexp1es mayor queexp2.

exp1>=exp2 verdaderosiexp1es mayor o igual aexp2.


exp1<exp2 verdaderosiexp1es menos queexp2.

exp1<=exp2 verdaderosiexp1es menor o igual aexp2.


exp1!=exp2 verdaderosiexp1no es igual aexp2(!se lee como “no”).
!Exp verdaderosiExpes falso yFALSOsiExpes verdad.

Además de los operadores relacionales, Java proporcionaoperadores logicosque se puede utilizar


para combinar/modificar expresiones lógicas. Los operadores lógicos más utilizados se enumeran en la
Tabla 2-4.
CAPITULO 2-ALGUNOS BASICOS DE JAVA 41

Tabla 2-4.Operadores lógicos de Java

Operador Descripción

exp1&&exp2 “y” lógico; La expresión compuesta es verdadera sólo siambosexp1yexp2son verdaderos “o”

exp1||exp2 lógicos; La expresión compuesta es verdadera sicualquieraexp1oexp2es verdad

!Exp “No” lógico; alterna el valor de una expresión lógica deverdaderoaFALSOy


viceversa

A continuación se muestra un ejemplo que utiliza el operador lógico "y" para programar la
expresión lógica compuesta "si x es mayor que 2,0 e y no es igual a 4,0":

si ((x > 2.0) && (y != 4.0)) { ... }

Las expresiones lógicas se utilizan con mayor frecuencia con estructuras de control de flujo, que se analizan más adelante
en este capítulo.

Evaluación de expresiones y precedencia de operadores


Como se mencionó anteriormente en este capítulo, las expresiones de complejidad arbitraria se pueden construir
superponiendo paréntesis anidados, por ejemplo, (((8 * (y + z)) + y) * x).El compilador generalmente evalúa dichas
expresiones desde el paréntesis más interno al más externo, de izquierda a derecha. Asumiendo quex, y,yzse
declaran e inicializan como se muestra aquí

entero x = 1;
int y = 2;
int z = 3;

entonces la expresión en el lado derecho de la siguiente declaración de asignación

respuesta int = ((8 * (y + z)) + y) * x;

Se evaluaría pieza por pieza de la siguiente manera:

((8 *(y+z) ) + y) * x
((8*5) +y) *x
(40 + años) * X
42*x
42

En ausencia de paréntesis, ciertos operadores tienen prioridad sobre otros en términos de cuándo se
aplicarán al evaluar una expresión. Por ejemplo, la multiplicación o división se realiza antes que la suma o
la resta. La precedencia de los operadores se puede modificar explícitamente mediante el uso de
paréntesis; Las operaciones realizadas dentro de paréntesis tienen prioridad sobre las operaciones fuera
de paréntesis. Considere el siguiente fragmento de código:

int j = 2 + 3 * 4; int k = // a j se le asignará el valor 14 // a k se


(2 + 3) * 4; le asignará el valor 20

En la primera línea de código, que no utiliza paréntesis, la operación de multiplicación tiene


prioridad sobre la operación de suma, por lo que la expresión general se evalúa como el valor 2 + 12
= 14; es como si hubiéramos escrito explícitamente2 + (3*4)sin tener que hacerlo.
42 CAPITULO 2-ALGUNOS BASICOS DE JAVA

En la segunda línea de código, se colocan explícitamente paréntesis alrededor de la operación 2 + 3


para que la operación de suma se realice primero y la suma resultante luego se multiplique por 4 para
obtener un valor de expresión general de 5 * 4 = 20.
Volviendo a un ejemplo anterior

si ((x > 2.0) && (y != 4.0)) { ... }

tenga en cuenta que los operadores > y != tienen prioridad sobre el operador &&, de modo que podríamos eliminar los
paréntesis anidados de la siguiente manera:

si (x > 2,0 && y != 4,0) { ... }

Sin embargo, los paréntesis adicionales ciertamente no hacen daño y, de hecho, se puede argumentar que
aclaran la intención de la expresión.

El tipo de expresión
Eltipo de expresiónes el tipo Java del valor al que finalmente se evalúa la expresión. Por
ejemplo, dado el fragmento de código

doble x = 3,0;
doble y = 2,0;
si ((x > 2.0) && (y != 4.0)) { ... }

la expresion (x > 2,0) && (y != 4,0)evalúa averdadero,y de ahí la expresión (x > 2,0) && (y != 4,0)se
dice que es unbooleanotipo expresión. Y, en el siguiente fragmento de código

entero x = 1;
int y = 2;
int z = 3;
respuesta int = ((8 * (y + z)) + y) * x;

la expresion ((8 * (y + z)) + y) * xevalúa a42,y de ahí la expresión ((8 * (y+z))


+y) *xse dice que es unEn t(eger) tipo expresión.

Conversiones de tipos automáticas y conversión explícita


Soportes de Javaconversión automática de tipos. Esto significa que si intentamos asignar un valor a una variable

// Pseudocódigo.
x =expresión;

y la expresión en ellado derechode la declaración de asignación se evalúa como undiferente


tipo que el tipo con el que la variable en ellado izquierdoSe declaró la declaración de asignación,
Java convertirá automáticamente el valor de la expresión de la derecha para que coincida con el
tipo deX,perosólo si no se pierde precisión al hacerlo. Esto se entiende mejor mirando un
ejemplo:

intx;
doble y;
y = 2,7;
x = y; // Estamos intentando asignar un valor doble a una variable int.
CAPITULO 2-ALGUNOS BASICOS DE JAVA 43

En el fragmento de código anterior, intentamos asignar eldoblevalor dey,2.7, aX,que se declara


como unEn t.Si esta cesión se llevara a cabo, la parte fraccionaria deysería truncado yXterminaría con
un valor entero de 2. Esto representa una pérdida de precisión, también conocida comoreducción de
la conversión.
El compilador AC o C++ permitirá esta asignación, truncando silenciosamente el valor. Sin embargo, en lugar
de asumir que esto es lo que pretendemos hacer, el compilador de Java generará un error en la última línea de
código de la siguiente manera:

posible pérdida de precisión


encontrada: doble
requerido: int

Para indicarle al compilador de Java que estamos dispuestos a aceptar la pérdida de precisión,
debemos realizar unareparto explícito—Es decir, debemos anteponer la expresión cuyo valor se va a
convertir con el tipo de destino, encerrado entre paréntesis:

// Pseudocódigo.
x = (tipo)expresión;

En otras palabras, tendríamos que reescribir la última línea del ejemplo anterior de la siguiente manera para
que el compilador de Java permita la asignación de un valor de punto flotante más preciso a una variable entera
menos precisa:

intx;
doble y;
y = 2,7;
x = (int) y; // Esto se compilará ahora, porque // hemos informado
explícitamente al compilador que QUEREMOS un
// reducción de la conversión para que se produzca.

Por supuesto, si tuviéramos quecontrarrestarla dirección de la tarea, asignando elEn tvalor de la


variableXhaciadoblevariabley,el compilador de Java no tendría ningún problema con la asignación:

intx;
doble y;
x = 2;
y = x; // Asigne un valor int menos preciso a una variable doble que sea capaz de //
manejar más precisión; esto está bien tal como está.

En este caso particular, estamos asignando un valor demenosprecisión—2—a una variable capaz demás
precisión;yterminará con el valor de 2.0. Esto se conoce como unconversión de ampliación. Estas
conversiones se realizan automáticamente en Java y no es necesario realizarlas explícitamente.
Tenga en cuenta que existe una idiosincrasia con respecto a la asignación de valores constantes a variables de tipo
flotaren Java; la siguiente declaración no se compilará:

flotar y = 3,5; // ¡Esto no se compilará!

porque un valor constante numérico con un componente fraccionario como3.5Java lo trata


automáticamente como un método más preciso.doblevalor, por lo que el compilador verá esto como una
conversión restringida y se negará a realizar la asignación. AfuerzaPara tal asignación, debemos convertir
explícitamente la constante de punto flotante en unaflotar:
44 CAPITULO 2-ALGUNOS BASICOS DE JAVA

flotar y = (flotar) 3,5; // Esto se compilará, gracias al elenco.

o, alternativamente, podemos forzar que el compilador de Java vea la constante en el lado derecho de la
declaración de asignación como unaflotarusando el sufijoF,como se muestra aquí:

flotar y = 3,5F; // Bien, porque estamos indicando que la constante debe //


tratarse como un flotante, no como un doble.

Otra opción más es simplemente declarardobleen vez deflotarvariables siempre que deseemos representar
valores numéricos de punto flotante en un programa.

Normalmente usaremosdobles en lugar deflotars siempre que necesitemos declarar variables de punto flotante en nuestra

aplicación SRS en la Parte 3 del libro, solo para evitar estas molestias de conversión de tipos.

Expresiones de tipocarbonizarsese puede convertir a cualquier otro tipo numérico, como se ilustra en el siguiente
ejemplo:

carácter c = 'a';

// Asignar un valor char a una variable numérica transfiere su // valor


numérico equivalente ASCII.
int x = c;
flotar y = c;
doble z = c;

System.out.println(x);
System.out.println(y);
System.out.println(z);

Aquí está la salida:

97
97.0
97.0

El único tipo de Java que no se puede convertir, ni implícita ni explícitamente, en otro tipo es el
booleanotipo.
Verás otras aplicaciones del casting, que involucran objetos, más adelante en el libro.

Bucles y otras estructuras de control de flujo


Muy raramente un programa se ejecutará secuencialmente, línea por línea, de principio a fin. En cambio, la ruta de
ejecución a través de la lógica de un programa a menudo serácondicional.

• Puede ser necesario que el programa ejecute un determinado bloque de código si se cumple alguna
condición, o unadiferentebloque de código si la condiciónno esreunió.

• Es posible que un programa tenga que ejecutar repetidamente un bloque particular de código un número fijo de
veces, o hasta que se logre un resultado particular.
CAPITULO 2-ALGUNOS BASICOS DE JAVA 45

El lenguaje Java proporciona varios tipos diferentes de bucles y otras estructuras de control de flujo para
solucionar estas situaciones.

si declaraciones
ElsiLa declaración es una declaración de rama condicional básica que ejecuta una o más líneas de código si se
cumple una condición, representada como una expresión lógica. Alternativamente, se pueden ejecutar una o más
líneas de código si la condición esnosatisfecho colocando ese código después de la palabra clave demás.El uso de
undemáscláusula con unasiLa declaración es opcional.
La sintaxis básica delsideclaración es la siguiente:

// Pseudocódigo.
si (expresión-lógica) {
ejecute cualquier código contenido entre estas llaves si la
expresión lógica se evalúa como verdadera
}

O agregando un opcionaldemáscláusula:

// Pseudocódigo.
si (expresión-lógica) {
ejecute cualquier código contenido entre estas llaves si la
expresión lógica se evalúa como verdadera
}
demás {
ejecute cualquier código contenido entre estas llaves si la
expresión lógica se evalúa como falsa
}

Si sólo una instrucción ejecutable sigue a lasio (opcional)demáspalabra clave, las llaves se
pueden omitir, como se muestra aquí:

// Pseudocódigo.
si(expresión-lógica) declaración única para ejecutar si la expresión-lógica es verdadera;
demásdeclaración única para ejecutar si la expresión lógica es falsa;

Por ejemplo:

si (x > 3) y = x; de lo
contrario z = x;

Pero generalmente se considera una buena práctica utilizar siempre llaves de la siguiente manera:

si (x > 3) {
y = x;
}
demás {
z = x;
}

un solobooleanoLa variable, como forma simple de expresión booleana, puede servir como
expresión/condición lógica de unasideclaración. Por ejemplo, es perfectamente aceptable escribir lo
siguiente:
46 CAPITULO 2-ALGUNOS BASICOS DE JAVA

// Utilice la variable booleana "terminado" como indicador que se establecerá en verdadero


cuando // se complete alguna operación en particular.
booleano terminado;

// Inicializarlo en falso.
terminado = falso;

// Se han omitido los detalles del código intermedio, en el que el indicador puede o no
establecerse en // verdadero...

// Prueba la bandera.
if (terminado) { // equivalente a: if (terminado == verdadero) {
System.out.println("¡Hemos terminado! :o)");
}

El ! El operador (“no”) se puede utilizar para negar una expresión lógica, de modo que el bloque de código
asociado con unasiLa declaración se ejecuta cuando la expresión se evalúa comoFALSOen cambio:

if (!finalizado) { // equivalente a: if (terminado == falso)


System.out.println("NO hemos terminado... :op");
}

Al probar la igualdad de dos expresiones, recuerde que debemos usardossignos iguales


consecutivos, no solo uno:

if (x == 3) { // Tenga en cuenta el uso de signos dobles de igual (==) para probar la igualdad.
y = x;
}

Un error común que cometen los programadores principiantes de Java, particularmente aquellos que han programado previamente en C o

C++, es intentar utilizar unsolterosigno igual para probar la igualdad, como en este ejemplo:

// Tenga en cuenta el uso incorrecto del signo igual único a


continuación. si (x = 3) {
y = x;
}
En Java, unsiLa prueba debe basarse en una prueba válida.lógicoexpresión;x = 3no es una expresión lógica, sino más bien

unaasignaciónexpresión. De hecho, lo anteriorsiLa declaración ni siquiera se compilará en Java, mientras queharíacompilar en

los lenguajes de programación C y C++, porque en esos lenguajes,siLas pruebas se basan en la evaluación de expresiones ya sea

para elenterovalor 0 (interpretado en el sentido deFALSO)o distinto de cero (interpretado en el sentido deverdadero).

Es posible anidarsi noConstrucciones para probar más de una condición. Si está anidado, un interior si (más
opcionaldemás)declaración se coloca dentro deldemásparte de un exteriorsi.La sintaxis básica para un anidado de
dos niveles.si noLa construcción se muestra aquí:
CAPITULO 2-ALGUNOS BASICOS DE JAVA 47

si (expresión-lógica-1) {
ejecuta este código
}
demás {
si (expresión-lógica-2) {
ejecuta este código alternativo
}
demás {
ejecute este código si ninguna de las expresiones anteriores se evalúa como verdadera
}
}

No hay límite para el número de anidadossi noSe pueden utilizar construcciones, aunque si se anida demasiado
profundamente, el código puede resultar difícil de entender y, por tanto, de mantener para un lector humano.
el anidadosiLa declaración que se muestra en el ejemplo anterior también se puede escribir sin utilizar
anidamiento de la siguiente manera:

si (expresión-lógica-1) {
ejecuta este código
}
más si(expresión-lógica-2) {
ejecuta este código alternativo
}
demás {
ejecute este código si ninguna de las expresiones anteriores se evalúa como verdadera
}

Tenga en cuenta que las dos formas son lógicamente equivalentes.

declaraciones de cambio
Acambiardeclaración es similar a unasi noconstruir porque permite la ejecución condicional de una o más líneas
de código. Sin embargo, en lugar de evaluar una expresión lógica como unasi no construcción lo hace, uncambiar
declaración compara el valor de unEn tocarbonizarseexpresión contra valores definidos por uno o máscaso
etiquetas. Si se encuentra una coincidencia, el código que sigue a la coincidencia casose ejecuta la etiqueta. Un
opcionalpor defectoSe puede incluir una etiqueta para definir el código que se ejecutará si elEn tocarbonizarse
coincidencias de expresiónningunodelcasoetiquetas.
La sintaxis general de uncambiardeclaración es la siguiente:

cambiar (expresión-int-o-char) {
casovalor1:
una o más líneas de código para ejecutar si el valor de la expresión coincide con el valor1
romper;
casovalor2:
una o más líneas de código para ejecutar si el valor de la expresión coincide con el valor2
romper;
// más etiquetas de casos, según sea necesario...
48 CAPITULO 2-ALGUNOS BASICOS DE JAVA

casovalorN:
una o más líneas de código para ejecutar si el valor de la expresión coincide con el valorN
romper;
por defecto:

código predeterminado para ejecutar si ninguno de los casos coincide


}

Por ejemplo:

// Se supone que x ha sido declarado previamente como int.


cambiar (x) {
caso 1: // ejecutado si x es igual a 1
System.out.println("Uno...");
romper;
caso 2: // ejecutado si x es igual a 2
System.out.println("Dos ...");
romper;
por defecto: // ejecutado si x tiene un valor distinto de 1 o 2
System.out.println("Ni uno ni dos...");
}

Tenga en cuenta lo siguiente:

• La expresión entre paréntesis que sigue a lacambiarLa palabra clave debe ser una expresión que se evalúe
comocarbonizarseoEn tvalor.

• Los valores que siguen elcasolas etiquetas deben ser valores constantes (una constante entera
“cableada” o un carácter literal).

• Los dos puntos (:), no el punto y coma (;), terminan elcasoypor defectoetiquetas.

• Las declaraciones que siguen a un determinadocasoLa etiqueta no tiene que estar entre llaves. Constituyen
unlista de declaracionesen lugar de un bloque de código.

A diferencia de unsideclaración, uncambiarLa declaración no finaliza automáticamente cuando se encuentra una


coincidencia y el código que sigue a la coincidenciacasose ejecuta la etiqueta. Para salir de uncambiardeclaración, un
romperSe debe utilizar la declaración. si unromperLa declaración no se incluye después de un determinadocasoetiqueta,
la ejecución "fallará" en la siguientecasoopor defectoetiqueta. Este comportamiento se puede utilizar a nuestro favor:
cuando se va a ejecutar la misma lógica para más de uncasoetiqueta, dos o máscaso Las etiquetas se pueden apilar
espalda con espalda, como se muestra aquí:

// se supone que x ha sido declarado previamente como un int


switch (x) {
caso 1:
código a ejecutar six es igual a 1
caso 2:
código a ejecutar six es igual a 1 O 2 caso
3:
código a ejecutar six es igual a 1, 2 o 3 romper;

caso 4:
código a ejecutar six es igual a 4
}
CAPITULO 2-ALGUNOS BASICOS DE JAVA 49

para declaraciones
Aparadeclaración es una construcción de programación que se utiliza para ejecutar una o más declaraciones
un cierto número de veces. La sintaxis general delparadeclaración es la siguiente:

para (inicializador;condición; iterador) {


código para ejecutar mientras la condición se evalúa como verdadera
}

AparaLa declaración define tres elementos que están separados por punto y coma y colocados entre
paréntesis después delparapalabra clave: elinicializador, elcondición, y eliterador. Elinicializador Se
utiliza para proporcionar un valor inicial para unvariable de control de bucle. La variable se puede declarar
como parte del inicializador o se puede declarar antes en el código, antes delparadeclaración, por ejemplo:

// La variable de control de bucle 'i' se declara dentro de la declaración for:


para (int yo = 0; condición; iterador) {
código para ejecutar mientras la condición se evalúa como verdadera
}
// Tenga en cuenta que el compilador ya no reconoce i cuando sale el bucle 'for', //
porque se declaró efectivamente dentro del bucle 'for'; hablaremos sobre // el alcance de
una variable más adelante en este capítulo .

versus

// La variable de control del bucle 'i' se declara antes del inicio del bucle 'for': ent yo;

para (yo = 0; condición; iterador) {


código para ejecutar mientras la condición se evalúa como verdadera
}

Elcondiciónes una expresión lógica que normalmente involucra la variable de control de bucle:

para (int i = 0;yo < 5; iterador) {


código para ejecutar siempre y cuando el valor de i permanezca menor que 5
}

Eliteradornormalmente incrementa o disminuye la variable de control del bucle:

para (int i = 0;yo < 5; yo ++ ) {


código para ejecutar siempre y cuando el valor de i permanezca menor que 5
}

Nuevamente, tenga en cuenta el uso de un punto y coma (;) después del inicializador y la condición, peronodespués del
iterador.
A continuación se muestra un desglose de cómoparael bucle opera:

1.Cuando la ejecución del programa alcanza unparadeclaración, el inicializador se ejecuta primero (y sólo
una vez).

2. Luego se evalúa la condición. Si la condición se evalúa como verdadera, se ejecuta el


bloque de código que sigue al paréntesis.
50 CAPITULO 2-ALGUNOS BASICOS DE JAVA

3.Una vez finalizado el bloque de código, se ejecuta el iterador.

4.Luego se reevalúa la condición. Si la condición aún esverdadero,el bloque de código se ejecuta una
vez más, seguido de la ejecución de la declaración del iterador.

Este proceso se repite hasta que la condición se vuelveFALSO,en cuyo punto elparael bucle termina.
A continuación se muestra un ejemplo sencillo que utiliza anidados.paradeclaraciones para generar una tabla de
multiplicar simple. Las variables de control del bucle,jyk,están declarados dentro de sus respectivosparadeclaraciones.
Siempre que se cumplan las condiciones en el respectivoparase cumplen las declaraciones, el bloque de código que
sigue a laparase ejecuta la declaración. El operador ++ se utiliza para incrementar los valores dejykcada vez que se
ejecuta el respectivo bloque de código.

clase pública para demostración {

público estático vacío principal (String [] argumentos) {


// Calcula una tabla de multiplicar simple.
para (int j = 1; j <= 4; j++) {
para (int k = 1; k <= 4; k++) {
System.out.println(j + " * " + k + " = " + (j * k));
}
}
}
}

Aquí está la salida:

1*1=1
1*2=2
1*3=3
1*4=4
2*1=2
2*2=4
2*3=6
2*4=8
3*1=3
3*2=6
3*3=9
3 * 4 = 12
4*1=4
4*2=8
4 * 3 = 12
4 * 4 = 16

Al igual que con otras estructuras de control de flujo, si sólo se especifica una declaración después de lapara
condición, se pueden omitir las llaves:

para (int i = 0; i < 3; i++) suma = suma + i;

pero se considera una buena práctica de programación usar llaves independientemente:

para (int i = 0; i < 3; i++) {


suma = suma + i;
}
CAPITULO 2-ALGUNOS BASICOS DE JAVA 51

mientras declaraciones
Amientrasdeclaración es similar en función a unaparadeclaración, en el sentido de que ambos se utilizan para ejecutar
repetidamente un bloque de código asociado. Sin embargo, si no es práctico predecir el número de veces que se
ejecutará el bloque de código cuando el ciclo comienza por primera vez,mientrasLa declaración es la opción preferida,
porque unamientrasLa declaración continúa ejecutándose mientras se cumpla una condición especificada.
La sintaxis general para elmientrasdeclaración es la siguiente:

mientras (condición) {
código que se ejecutará repetidamente mientras la condición continúa evaluándose como verdadera
}

La condición puede ser una expresión lógica simple o compleja que se evalúa como una
verdaderooFALSOvalor, por ejemplo:

entero x = 1;
int y = 1;

mientras ((x < 20) || (y < 10)) {


¡Con suerte haremos algo dentro del cuerpo de este bucle que incremente el valor de x o
y, para evitar un bucle infinito!
}

Cuando la ejecución del programa alcanza unmientrasdeclaración, la condición se evalúa primero. Si la


condición esverdadero,Se ejecuta el bloque de código que sigue a la condición. Cuando el bloque de código
finaliza, la condición se evalúa nuevamente y, si aún persiste,verdadero,El proceso se repite hasta que la
condición se evalúa comoFALSO,en cuyo punto elmientrasel bucle termina.
He aquí un ejemplo sencillo que ilustra el uso de unmientrasbucle para imprimir valores enteros
consecutivos de 0 a 3. Abooleanovariable nombradafinalizadoinicialmente se establece enFALSO.ElfinalizadoLa
variable se utiliza como bandera: siempre y cuandofinalizadoesFALSO,el bloque de código que sigue almientrasEl
bucle continuará ejecutándose. Cuando el valor deillega a 4, elfinalizadola bandera se establecerá enverdadero,en
cuyo punto elmientrasEl bucle terminará.

clase pública MientrasDemo {


público estático vacío principal (String [] argumentos) {
booleano terminado = falso;
int yo = 0;

mientras (!terminado) {
System.out.println(i);
yo ++;
si (i == 4) terminado = verdadero; // alterna la bandera para terminar el ciclo
}
}
}

Aquí está la salida:

0
1
2
3
52 CAPITULO 2-ALGUNOS BASICOS DE JAVA

Al igual que con las otras estructuras de control de flujo, si sólo se especifica una declaración después de la
condición, se pueden omitir las llaves:

mientras (x < 20) x = x * 2;

pero se considera una buena práctica de programación usar llaves independientemente:

mientras (x < 20) {


x = x * 2;
}

Declaraciones de salto
El lenguaje Java define dosdeclaraciones de saltoque se utilizan para redirigir la ejecución del programa a
otra declaración en otra parte del código. Los dos tipos de declaración de salto son losrompery continuar
declaraciones.
ya has vistoromperdeclaraciones en acción anteriormente en este capítulo, cuando se usaron junto con
cambiardeclaraciones. AromperLa declaración también se puede utilizar para terminar abruptamente unaparao
mientrasbucle. Cuando unromperSe encuentra una declaración durante la ejecución del bucle, el bucle termina
inmediatamente y la ejecución del programa se transfiere a la línea de código que sigue inmediatamente al bucle,
como en el siguiente ejemplo:

// Comenzamos con la intención de incrementar x de 1 a 4... for (int x = 1; x <=


4; x++) {
// ... pero cuando x alcanza el valor 3, terminamos prematuramente este //
bucle con una instrucción break.
si (x == 3) romper;
System.out.println(x);
}

System.out.println("Bucle finalizado");

El resultado producido por este código sería el siguiente:

1
2
Bucle terminado

AcontinuarLa declaración, por otro lado, se utiliza para salir deliteración actualde un bucle sin
terminandoen generalejecución del bucle. Eso es uncontinuarLa declaración transfiere la ejecución del
programa de regreso a la parte superior del ciclo sin finalizar la iteración particular que ya está en
progreso; el contador de bucle se incrementa, en el caso de unparabucle y la ejecución continúa.
Veamos el mismo ejemplo que antes, pero reemplazaremos elromperdeclaración con uncontinuar
declaración:

// Comenzamos con la intención de incrementar x de 1 a 4... for (int x = 1; x <=


4; x++) {
// ... pero cuando x alcanza el valor 3, terminamos prematuramente // esta
iteración del bucle (únicamente) con una instrucción de continuación.
CAPITULO 2-ALGUNOS BASICOS DE JAVA 53

si (x == 3) continúa;
System.out.println(x);
}

System.out.println("Bucle finalizado");

El resultado producido por este código sería el siguiente:

1
2
4
Bucle terminado

Lenguajes estructurados en bloques y el alcance de


una variable
Java (como C y C++) es unlenguaje estructurado en bloques. Como se mencionó anteriormente en este
capítulo, un "bloque" de código es una serie de cero o más líneas de código encerradas entre llaves {...}.
Los bloques se pueden anidar uno dentro de otro hasta cualquier profundidad arbitraria, como se ilustra en el siguiente
ejemplo de código:

clase pública Programa Simple {


// Estamos dentro del bloque "clase" (un nivel de profundidad). público
estático vacío principal (String [] argumentos) {
// Estamos dentro del bloque "método principal" (dos niveles de profundidad).
entero x = 3;
int y = 4;
int z = 5;

si (x > 2) {
// Ahora estamos un nivel más profundo (nivel 3), en un bloque
"si". si (y > 3) {
// Estamos un nivel más profundo aún (nivel 4), en un //
bloque "si" anidado.
// (¡Podriamos seguir y seguir!)
} // Acabamos de terminar el bloque del nivel 4.
// (Podríamos tener código adicional aquí, en el nivel 3.) } // ¡El
nivel 3 está terminado!
// (Podríamos tener código adicional aquí, en el nivel 2.) } //
¡Eso es todo para el nivel 2!
// (Podríamos tener código adicional aquí, en el nivel 1.)
} // ¡Adiós, amigos! El nivel 1 (el bloque "clase") acaba de finalizar.

Las variables se pueden declarar en cualquier bloque dentro de un programa. Elalcancede una variable es esa
parte del código en la que se puede hacer referencia a la variable por su nombre, específicamente, desde el punto donde
el nombre de la variable se declara por primera vez hasta la llave de cierre (derecha) del bloque de código en el que se
declaró. Se dice que una variable esen alcancesiempre y cuando el compilador reconozca su
54 CAPITULO 2-ALGUNOS BASICOS DE JAVA

nombre. Una vez que la ejecución del programa sale de un bloque de código, cualquier variable que se haya declarado
dentro de ese bloque desaparece.fuera del ámbitoy será inaccesible al programa; el compilador efectivamente olvida
que la variable alguna vez fue declarada.
Como ejemplo de las consecuencias del alcance variable, veamos un programa simple llamado
AlcanceEjemplo.Este programa hace uso de tres bloques de código anidados: uno para elclasecuerpo, uno para el
principalcuerpo del método, y otro como parte de unsideclaración dentro del cuerpo delprincipalmétodo. A su vez
declaramos dos variables:X,en elprincipalbloque de código (en el nivel 2), yy,en elsibloque (nivel 3).

public class ScopeExample { // Inicio del nivel de bloque 1.


public static void main(String[] args) { // Inicio del nivel de bloque 2.
doble x = 2,0; // Declarar "x" en el nivel de bloque 2.

if (x < 5.0) { // Inicio del nivel de bloque 3.


doble y = 1,0; // Declarar "y" dentro del nivel de bloque 3.
System.out.println("El valor de x = " + x); // x, declarado en el nivel 2, // todavía
está dentro del alcance del nivel 3.
System.out.println("El valor de y = " + y);
} // La variable "y" sale del alcance cuando finaliza el bloque "if" (nivel 3).

// "y" ha salido del alcance y el compilador ya no lo reconoce. // Si intentamos hacer


referencia a "y" en una declaración posterior, el compilador // generará un error. "x",
por otro lado, permanece dentro del alcance hasta que finaliza el bloque de método
principal // (nivel 2).

System.out.println("El valor de x = " + x); // Esto se compilará. //


System.out.println("El valor de y = " + y); Esto NO se compilará.
} // La variable "x" sale del alcance cuando finaliza el bloque del método principal (nivel 2).
}

En el ejemplo anterior, la variableysale del alcance tan pronto comosiextremos del bloque. Si intentamos
accederyMás adelante en el programa, como lo hacemos en la línea en negrita del código anterior, el compilador
generará el siguiente mensaje de error:

no se puede resolver el símbolo

símbolo: variable y System.out.println("El


valor de y = " +y);
^

Tenga en cuenta que una variable determinada es accesible para cualquier anidado.internobloques de código
que siguen a su declaración. Por ejemplo, en el anteriorAlcanceEjemploprograma, variableX,declarado en el principal
nivel de bloque de método (nivel 2), es accesible dentro delsibloque de código de declaración (nivel 3).

Imprimir en la pantalla
La mayoría de las aplicaciones comunican información a los usuarios mostrando mensajes a través de la GUI de una
aplicación. Sin embargo, a veces también es útil poder mostrar mensajes de texto simples en la ventana de línea de
comandos desde la que estamos ejecutando un programa como una forma rápida y sucia de verificar que un programa
está funcionando correctamente. Hasta que analicemos cómo crear una GUI Java en los Capítulos 16 y 17, esta será la
forma principal de comunicación de nuestro programa con el mundo exterior.
CAPITULO 2-ALGUNOS BASICOS DE JAVA 55

Para imprimir mensajes de texto en pantalla utilizamos la siguiente sintaxis:

Sistema.fuera.println(expresión a imprimir);

ElSystem.out.printlnEl método puede aceptar expresiones muy complejas y hace todo lo posible
para convertirlas en una sola.Cadenavalor, que luego se muestra en la pantalla. Aquí están algunos
ejemplos:

System.out.println("¡Hola!"); // Imprimir una cadena literal/constante.

Cadena s = "¡Hola!";
System.out.println(s); //Imprimiendo el valor de una variable String.

Cadena t = "foo"; Cadena u = "barra";


System.out.println(t + u + "!");
// Usando el operador de concatenación de cadenas (+) //
para imprimir "foobar!".
entero x = 3;
int y = 4;
System.out.println(x); // Imprime la representación en cadena del //
valor entero 3 en la pantalla.
System.out.println(x + y); // Calcula la suma de x e y, luego imprime la //
representación en cadena del valor entero 7 // en la
pantalla.

Tenga en cuenta que en la última línea de código el signo más (+) se interpreta como elsumaoperador, no
como elCadenaconcatenaciónoperador, porque separa dos variables que están declaradas como de tipoEn t.
Entonces, se calcula que la suma de 3 + 4 es 7, que luego se imprime. Sin embargo, en el siguiente ejemplo
obtenemos un comportamiento diferente (y posiblemente no deseado):

System.out.println("La suma de x más y es: " + x + y);

La línea de código anterior hace que se imprima lo siguiente:

La suma de x más y es: 34

¿Por qué es esto? Recuerde que evaluamos expresiones de izquierda a derecha, por lo que como el
primero de los dos signos más separa unaCadenaliteral y unEn t

System.out.println("La suma de x más y es: " + x +y);

El primer signo más se interpreta como unCadenaoperador de concatenación, que produce el intermediario
Cadenavalor "La suma de x más y es: 3".El segundo signo más separa este intermedioCadena valor de unEn
t,y entonces el segundo signo más estambiéninterpretado como unCadenaoperador de concatenación,
produciendo el finalCadenavalor "La suma de x más y es: 34",que se imprime en la ventana de comandos.

Para imprimir elcorrectola suma deXyy,debemos forzar que el segundo signo más se interprete como un
operador de suma de números enteros encerrando la expresión de suma entre paréntesis anidados:

System.out.println("La suma de x más y es: " + (x + y));

Los paréntesis anidados hacen que la expresión más interna se evalúe primero, calculando así la suma dex + y
adecuadamente. Por lo tanto, esteimprimirLa declaración muestra el mensaje correcto en la pantalla:
56 CAPITULO 2-ALGUNOS BASICOS DE JAVA

La suma de x más y es: 7

Al escribir código que involucra expresiones complejas, es una buena idea usar paréntesis generosamente para
dejar claras sus intenciones al compilador. Los paréntesis adicionales, cuando se usan correctamente, ¡nunca hacen
daño!

imprimir versus imprimir

Cuando llamamos alSystem.out.printlnmétodo, se imprimirá cualquier expresión encerrada entre


paréntesis, seguida de un (dependiente de la plataforma)terminador de línea. El siguiente fragmento de
código

System.out.println("Primera línea.");
System.out.println("Segunda línea.");
System.out.println("Tercera línea.");

produce tres líneas separadas de salida:

Primera linea.
Segunda linea.
Tercera línea.

Por el contrario, la declaración

Sistema.fuera.imprimir(expresión a imprimir);

hace que se imprima cualquier expresión entre paréntesissinun terminador de línea final. Usando
imprimiren combinación conimprimirnos permite generar unsolterolínea de salida a través de un
seriede sentencias Java, como se muestra en el siguiente ejemplo:

System.out.print("J"); // Usando imprimir aquí. //


System.out.print("AV"); Usando imprimir aquí.
System.out.println("¡¡¡A!!!"); // Tenga en cuenta el uso de println como última declaración.

Este fragmento de código produce una sola línea de salida:

¡¡¡JAVA!!!

Cuando una única declaración impresa es demasiado larga para caber en una sola línea, como en este ejemplo:

// Pseudocódigo.
declaración;
otra declaración;
System.out.println("Aquí hay un ejemplo de una declaración de
impresión única que es muy larga... TAN larga que se envuelve y hace que la lista del
programa sea difícil de leer.");
otra declaración más;

Podemos hacer que una lista de programas sea más legible dividiendo el contenido de dicha declaración en
múltiples enlaces concatenados.Cadenaexpresiones y luego dividir la declaración a lo largo de límites de signo
más:
CAPITULO 2-ALGUNOS BASICOS DE JAVA 57

// Pseudocódigo.
declaración;
otra declaración;
System.out.println("Aquí hay un ejemplo de cómo " +
"para dividir una declaración impresa larga " +
"con signos más.");
otra declaración más;

Aunque lo anteriorSystem.out.printlnLa llamada se divide en tres líneas de código, se


imprimirá como una sola línea de salida:

A continuación se muestra un ejemplo de cómo dividir una declaración impresa larga con signos más.

Secuencias de escape
Java define una serie desecuencias de escapepara que podamos representar caracteres especiales, como
caracteres de nueva línea y tabulación, dentroCadenaocarbonizarseliterales. Las secuencias de escape más
utilizadas se enumeran en la Tabla 2-5.

Tabla 2-5.Secuencias de escape de Java

Secuencia de escape Descripción

\norte Nueva línea

\b Retroceso
\t Pestaña

\\ Barra invertida

\' Una frase; utilizado entre comillas simples (p. ej.,char singleQuote = '\'';) Comilla

\" doble; utilizado entre comillas dobles (por ejemplo,Cadena dobleQuote = "\"";)

Se pueden incluir una o más secuencias de escape en la expresión que se pasa alimprimir y
imprimirmétodos. Por ejemplo, considere el siguiente fragmento de código:

System.out.println("Uno..."); System.out.println("\t... dos ...");


System.out.println("\t\t... tres... \"¡¡¡RUEE!!!\"");

Cuando se ejecuta el código anterior, se muestra el siguiente resultado:

Uno ...
. . . dos ...
. . . tres... "¡¡¡BIEE!!!"

La segunda y tercera línea de salida han sido sangradas una y dos posiciones de tabulación,
respectivamente, en virtud del uso de \yo,y la expresión "¡¡¡VAYA!!!"se imprime entre comillas dobles
debido a nuestro uso de \".
58 CAPITULO 2-ALGUNOS BASICOS DE JAVA

Elementos del estilo Java


Una de las características de los buenos programadores es que producenlegible por humanos
código, para que sus colegas puedan trabajar y modificar sus programas. Las siguientes
secciones presentan algunas pautas y convenciones que le ayudarán a producir código Java
claro y legible.

Uso adecuado de la sangría


Una de las mejores formas de hacer legible un programa Java es mediante el uso adecuado de sangría para
delinear claramente su estructura de bloques. Las declaraciones dentro de un bloque de código deben tener
sangría relativa a la línea inicial/final del bloque circundante (es decir, sangría relativa a las líneas que llevan las
llaves). La recomendación de Sun Microsystems es utilizar cuatro espacios (tenga en cuenta que algunos de los
ejemplos de este libro difieren de ese estándar).
Para ver cómo la sangría puede hacer que un programa sea legible, considere los dos programas siguientes.
En el primer programa simple, se utiliza la sangría adecuada:

ejemplo de sangría de clase pública {


público estático vacío principal (String [] argumentos) {
para (int i = 1; i <= 4; i++) {
Sistema.out.print(i);

si ((yo == 2) || (yo == 4)) {


si (yo == 2) {
System.out.print("Dos ");
}
demás {
System.out.print("Cuatro ");
}
System.out.println("es un número par");
}
de lo contrario si ((i == 1) || (i == 3)) {
si (yo == 1) {
System.out.print("Uno ");
}
demás {
System.out.print("Tres ");
}
System.out.println("es un número impar");
}
}
}
}

y es relativamente fácil ver cómo se produciría el siguiente resultado:


CAPITULO 2-ALGUNOS BASICOS DE JAVA 59

1 es un número impar
2 es un número par 3
es un número impar 4
es un número par

Ahora eliminemos toda sangría del programa:

public class IndentationExample { public


static void main(String[] args) { for (int i = 1; i
<= 4; i++) {
Sistema.out.print(i);

si ((yo == 2) || (yo == 4)) { si (yo


== 2) {
System.out.print("Dos "); }

demás {
System.out.print("Cuatro "); }

System.out.println("es un número par"); }

de lo contrario si ((i == 1) || (i == 3))


{ si (i == 1) {
System.out.print("Uno "); }

demás {
System.out.print("Tres "); }

System.out.println("es un número impar"); }

}
}
}

El compilador de Java comprende ambas versiones de este programa y ambas producen el mismo resultado
cuando se ejecutan, pero la primera versión es mucho más legible para un ser humano.
No aplicar una sangría adecuada no sólo hace que los programas sean ilegibles, sino que también los hace
más difíciles de depurar, especialmente si surge un error de compilación debido a llaves desequilibradas o
faltantes. En tal situación, el mensaje de error de compilación a menudo aparece en una línea mucho más tarde
en el programa que donde realmente existe el problema. Por ejemplo, al siguiente programa le falta una llave de
apertura/izquierda en la línea 9, pero el compilador no informa un error hasta la línea 23:

clase pública Ejemplo de sangría2 {


público estático vacío principal (String [] argumentos) {
entero x = 2;
int y = 3;
int z = 1;
60 CAPITULO 2-ALGUNOS BASICOS DE JAVA

si (x >= 0) {
si (y > x) {
if (y > 2) // nos falta una llave izquierda aquí en la línea 9, pero...
Sistema.salida.println("A");
z = x + y;
}
demás {
Sistema.salida.println("B");
z = x - y;
}
}
demás {
System.out.println("C"); z =
y - x;
}
}
else System.out.println("D"); // ... ¡el compilador primero se queja aquí!
// (línea 23)
}
}

Lo que es aún peor, el mensaje de error que genera el compilador en tal situación puede ser
bastante críptico. En este ejemplo particular, el compilador (incorrectamente) señala la línea 23 como el
problema, con un mensaje de error engañoso:

IndentationExample2.java:23: inicio ilegal del tipo else


System.out.println("D");
^

Este mensaje de error no nos ayuda a localizar elrealproblema en la línea 9. Sin embargo, al menos
hemos sangrado correctamente nuestro código, por lo que probablemente será mucho más fácil encontrar
la llave que falta que si nuestra sangría fuera descuidada o inexistente.

Si alguna vez recibe un error de compilación que no tiene ningún sentido, considere buscar en una etapa anterior del programa

la puntuación que falta, es decir, una llave, un paréntesis o un punto y coma que faltan.

A veces, tenemos tantos niveles de sangría anidada, o las declaraciones individuales son tan largas,
que las líneas se ajustan cuando se ven en un editor o se imprimen en papel:
CAPITULO 2-ALGUNOS BASICOS DE JAVA 61

mientras (a <b) {
mientras (c > d) {
para (int j = 0; j < 29; j++) {
x = y + z + a - b + (c * (d / e) + f) -
g + h + j - l - m - n + o + p * q / r + s;
}
}
}

Para evitar esto, es mejor dividir la línea en cuestión a lo largo de espacios en blanco o límites de
puntuación, sangrando las líneas de continuación con respecto al inicio de la línea:

mientras (a <b) {
mientras (c > d) {
para (int j = 0; j < 29; j++) {
// Esto es cosméticamente preferido. // Sangría de notas
de líneas de continuación.
x = y + z + a - b + (c * (d / e) + f) -
g + h + j - l - m - n + o + p * q / r + s;

}
}
}

Utilice los comentarios sabiamente

Otra característica importante que hace que el código sea más legible es el uso liberal de comentarios significativos.
Siempre tenga en cuenta al escribir código quetúEs posible que sepa lo que está intentando hacer, pero es posible que
otra persona que intente leer su código no lo sepa. (En realidad, a veces incluso necesitamos recordarnosotros
mismosde por qué hicimos lo que hicimos si no hemos mirado el código que hemos escrito por un tiempo!)

Aquí hay algunas reglas básicas:

• Si puede haber alguna duda sobre lo que hace un pasaje de código, precedido con un comentario.

• Sangrar cada comentario al mismo nivel que el bloque de código o declaración al que se
aplica.

• Asegúrese de que todos los comentarios agreguen valor; no diga lo obvio, como en el siguiente comentario
bastante inútil:

// Declaramos x como un número entero y le asignamos un valor inicial de 3.


int x = 3;

Colocación de aparatos ortopédicos

Para los lenguajes estructurados en bloques que utilizan llaves para delimitar el inicio/final de los bloques (por ejemplo, C, C++,
C#, Java), existen dos escuelas generales de pensamiento sobre dóndeizquierda/aperturaSe debe colocar la llave de un bloque
de código.
62 CAPITULO 2-ALGUNOS BASICOS DE JAVA

El primer estilo consiste en colocar una llave de apertura en elfinde la línea de código que inicia un bloque
determinado. Cada llave de cierre va en su propia línea, alineada con laprimerocarácter de la línea que contiene
la llave de apertura:

Prueba de clase pública {


público estático vacío principal (String [] argumentos) {
para (int i = 0; i < 3; i++) {
System.out.println(i);
}
}
}

Un estilo alternativo de colocación de tirantes es colocar cada tirantes de apertura en una línea separada,
alineada con la línea inmediatamente anterior. Cada llave de cierre va en su propia línea como antes, alineada con
la llave de apertura correspondiente:

prueba de clase pública


{
público estático vacío principal (String [] argumentos) {

para (int i = 0; i < 3; i++) {

System.out.println(i);
}
}
}

Cualquiera de los dos métodos para colocar el aparato ortopédico izquierdo o de apertura está bien; El primero de
los dos enfoques produce listados de códigos que son un poco más compactos (es decir, contienen menos espacios en
blanco) y es el más popular de los dos estilos. Sin embargo, es una buena práctica mantener la coherencia en el código,
así que elija el estilo de colocación de llaves que prefiera y manténgalo.

Nombres de variables descriptivas


Al igual que con la sangría y los comentarios, el objetivo al elegir nombres de variables es hacer que un programa sea lo
más legible y, por tanto, autodocumentado posible. Evite el uso de letras individuales como nombres de variables,
excepto para variables de control de bucle (o como parámetros de métodos, que se analizan más adelante en el libro).

Las abreviaturas se deben utilizar con moderación y solo cuando se utilicen habitualmente y los
desarrolladores las entiendan ampliamente. Considere la siguiente declaración de variable:

grado int;

No está del todo claro cuál es el nombre de la variable.grdse supone que representa. ¿Se supone que la variable
representa una cuadrícula, una calificación o una calabaza? Una mejor práctica sería deletrear la palabra
completa:

grado internacional;
CAPITULO 2-ALGUNOS BASICOS DE JAVA 63

En el otro extremo del espectro, nombres demasiado largos (como quizás

doble promedio de retorno de la inversión del tercer trimestre;

puede hacer que una lista de códigos sea abrumadora para cualquiera que intente leerla. A veces puede resultar
complicado acortar el nombre de una variable sin dejar de ser descriptivo, pero intenta mantener la longitud de los
nombres de las variables dentro de lo razonable, por ejemplo:

doble avg3rdQtrROI;

Resumen
En este capítulo, ha aprendido algunas de las ventajas de Java como lenguaje de programación OO, es
decir, que

• Java es un elegante lenguaje de programación OO que mejora muchos lenguajes que lo


precedieron.

• Java fue diseñado desde cero para estar completamente orientado a objetos.

• Java es una arquitectura neutral.

• Todas las funciones necesarias para crear aplicaciones industriales están integradas en el
lenguaje central Java.

• Java es un lenguaje de código abierto.

• Java se puede descargar de forma gratuita desde Sun Microsystems.http://java.sun.comsitio web.

Además de explorar algunas de las ventajas de Java, también ha aprendido algunos elementos
básicos de la sintaxis de Java. En particular, cubrimos

• La anatomía de un programa Java simple

• La mecánica de cómo compilar y ejecutar un programa Java desde la línea de comandos

• Los ocho tipos primitivos de Java y elCadenatipo

• Cómo se declaran e inicializan las variables de estos tipos

• Cómo se puede convertir una expresión de un tipo en un tipo diferente y cuándo es necesario
hacerlo

• Expresiones y operadores aritméticos, de asignación, lógicos y relacionales.

• Bucles y otras estructuras de control de flujo disponibles con Java

• Cómo definir bloques de código y el concepto de alcance variable

• Cómo imprimir mensajes de texto con elSystem.out.printlnyImpresión.de.salida.del.sistemamétodos

• Algunos elementos básicos de un buen estilo de programación Java

Hay mucho más que aprender sobre Java (cosas que necesitará saber al crear la aplicación SRS en la Parte 3
del libro), pero primero necesito explicar una serie de conceptos básicos de objetos. Entonces, ¡pasemos al
Capítulo 3!
64 CAPITULO 2-ALGUNOS BASICOS DE JAVA

Ejercicios

1.Investigue Java en el sitio web de Sun,http://java.sun.com,y cite cualquier ventaja o característica de Java que no
se mencione en este capítulo.

2.Navegue un poco por la web para ver cómo otros proveedores han adoptado el lenguaje Java, por ejemplo,
IBM, Oracle, Microsoft y Apple.

3.Compare lo que ha aprendido sobre Java hasta ahora con otro lenguaje de programación con el que ya esté
familiarizado. ¿Qué tienen de similar los dos idiomas? ¿Que es diferente?

4.[Codificación] Cree un fragmento de código que imprimirá los números pares del 2 al 10 en la ventana de comandos
usando (a) unparabucle y uncontinuardeclaración y (b) unamientrasbucle y unbooleanovariable como bandera.

5.Dadas las siguientes declaraciones de variables iniciales y asignaciones de valores, evalúe la expresión en la última
línea de código:

int a = 1;
int b = 1;
int c = 1;
((((c++ + --a) * b) != 2) && verdadero)
CAPÍTULO 3
---

Objetos y clases

oh Los objetos son los componentes fundamentales de una aplicación orientada a objetos. Así como
aprendiste en el Capítulo 1 que la abstracción implica producir un modelo del mundo real, verás en este
capítulo que los objetos son “mini abstracciones” de los diversos elementos del mundo real que
componen dicho modelo.
En este capítulo aprenderás

• Las ventajas de un enfoque orientado a objetos para el desarrollo de software en comparación con el enfoque
"tradicional" no orientado a objetos orientados a objetos.

• Cómo utilizar clases para especificar los datos y el comportamiento de un objeto

• Cómo crear objetos en tiempo de ejecución

• Cómo declararvariables de referenciaPara referirse a objetos simbólicamente dentro de un programa.

• Cómo los objetos se siguen unos a otros en la memoria

Software en su forma más simple


En su forma más simple, cada aplicación de software consta de dos componentes principales:datosy funciones
que operan (es decir, ingresan, emiten, calculan, almacenan, recuperan, imprimen, etc.) esos datos. (Ver Figura
3-1.)

Figura 3-1.En su forma más simple, el software consta de datos y funciones que operan sobre esos datos.

sesenta y cinco
66 CAPÍTULO 3-OBJETOS Y CLASES

La forma anterior a OO de diseñar software se conocía como (De arriba hacia abajo)descomposición
funcional. Comparemos el enfoque de descomposición funcional del diseño de software con el enfoque OO.

Descomposición funcional
Con la descomposición funcional, comenzamos con una declaración de la función general que se
esperaba que realizara un sistema; por ejemplo, "Registro de estudiantes". Luego dividimos esa
función en subfunciones:

• “Agregar un nuevo curso al catálogo de cursos”

• “Permitir que un estudiante se inscriba en un curso”

• “Imprimir el horario de clases de un estudiante”

Etcétera.
A continuación, descompusimos esas funciones en subfunciones más pequeñas. Por ejemplo, podríamos
descomponer "Permitir que el estudiante se inscriba en un curso" en

• “Mostrar lista de cursos disponibles”

• “Permitir al estudiante seleccionar un curso”

• “Verificar que el estudiante haya cumplido con todos los requisitos previos”

etc. Seguimos descomponiendo funciones en partes lógicas cada vez más pequeñas hasta que razonablemente
no pudimos subdividir más, como se ilustra en la Figura 3-2.

Figura 3-2.Descompusimos funcionalmente una aplicación de arriba hacia abajo. . .

Luego asignamos las funciones de nivel más bajo a diferentes programadores para codificar yprueba de unidad(
es decir, prueba de forma aislada). Finalmente, ensamblamos estas funciones de forma modular desde abajo hacia
arriba, probando los resultados de cada etapa sucesiva en el proceso de integración, hasta que tuvimos una aplicación
completa construida, como se ilustra en la Figura 3-3.
CAPÍTULO 3-OBJETOS Y CLASES 67

Figura 3-3.. . .y ensamblé la aplicación de abajo hacia arriba.

Con el enfoque de descomposición funcional para el desarrollo de software, nuestro enfoque principal
fue lafuncionesque se iba a realizar una solicitud;datosfue una ocurrencia tardía. Eso es,

• Los datos pasaban de una función a la siguiente, como un automóvil que se fabrica a través de un
proceso de línea de ensamblaje en una planta automotriz.

• Por lo tanto, la estructura de los datos debía entenderse enmuchoslugares (es decir, por muchas funciones) a
lo largo de una aplicación.

• Si la estructura de datos de una aplicación tuvo que cambiar después de que se implementó la aplicación,A menudo
surgieron importantes "efectos dominó" a lo largo de la solicitud.. Uno de los ejemplos más dramáticos de un efecto
dominó debido a un cambio en la estructura de datos fue elCrisis del año 2000, donde un cambio aparentemente
simple en los formatos de fecha (de un año de dos a cuatro dígitos) causó pánico en todo el mundo.Miles de millonesSe
gastaron miles de dólares para tratar de encontrar y reparar lo que se esperaba que fueran efectos dominó desastrosos
antes de que el reloj marcara la medianoche del 1 de enero de 2000.

• A pesar de nuestros mejores esfuerzos para probar una aplicación exhaustivamente antes de implementarla, los
errores siempre logran pasar desapercibidos. Si surgían errores de integridad de datos como resultado de una
lógica defectuosa después de que una aplicación se había integrado completamente, a menudo era muy difícil
determinar con precisión dónde, es decir,en qué función(es) específica(s)—El error podría haber ocurrido
porque los datos se habían pasado de una función a otra muchas veces.

El enfoque orientado a objetos


Como verá en los próximos capítulos, el enfoque OO para el desarrollo de software soluciona la
gran mayoría de estas deficiencias.

• Con el desarrollo de software OO, nos enfocamos en diseñar la aplicación.estructura de datos


primero, y sus funciones, segundo.

• Los datos sonencapsuladointerior de objetos; por lo tanto, la estructura de los datos debe ser entendida únicamente por
el objeto al que pertenecen los datos.
68 CAPÍTULO 3-OBJETOS Y CLASES

• Si la estructura de datos de un objeto tiene que cambiar después de que se haya implementado la
aplicación, prácticamente haysin efectos dominó; sólo debe cambiar la lógica interna del objeto afectado.

• Cada objeto es responsable de garantizar la integridad de sus propios datos.. Por lo tanto, si surgen errores
de integridad de datos dentro de los datos de un objeto determinado, podemos asumir que fue el objeto sí
mismoeso permitió que esto sucediera y, por lo tanto, podemos centrarnos en la lógica funcional interna de ese
objeto para aislar el "error".

¿Qué es un objeto?
Antes de hablar de objetos de software, hablemos de los objetos del mundo real en general. Según el
Diccionario Universitario Merriam-Webster, un objeto es

(1) algo material que pueda ser percibido por los sentidos; (2) algo mental
o físico hacia el cual se dirige el pensamiento, sentimiento o acción.

La primera parte de esta definición se refiere a los objetos como normalmente pensamos en ellos: como
“cosas” físicas que podemos ver y tocar, y que ocupan espacio. Debido a que pretendemos utilizar el estudio de
caso del Sistema de registro de estudiantes (SRS) como base para aprender sobre objetos a lo largo de este libro,
pensemos en algunos ejemplos deobjetos fisicosque tienen sentido en el contexto general de un entorno
académico, a saber

• Elestudiantesque asisten a clases

• Elprofesoresquienes enseñan a los estudiantes

• Elaulasen el que se llevan a cabo las reuniones de clase

• Elequipo audiovisualen estas aulas

• Eledificiosen el que se encuentran las aulas

• Ellibros de textolos estudiantes usan

Etcétera. Por supuesto, si bien todos estos tipos de objetos se encuentran comúnmente en un campus
universitario típico, no todos son relevantes para registrar estudiantes en cursos, ni todos ellos necesariamente
aparecen en el estudio de caso de SRS, pero no nos preocuparemos. sobre eso por el momento. En la Parte 2 de
este libro, aprenderá una técnica para utilizar una especificación de requisitos como base para identificar qué
tipos de objetos son relevantes para una abstracción particular.
Ahora, centrémonos en la segunda mitad de la definición, particularmente en la frase“algo mental. . . hacia
el cual se dirige el pensamiento, sentimiento o acción”.Hay muchísimosobjetos conceptualesque
desempeñan papeles importantes en un entorno académico; algunos de estos son

• Elcursosque los estudiantes asistan

• Eldepartamentosque los profesores trabajan para

• Elgradosque los estudiantes reciben

y, por supuesto, muchos otros. Aunque no podemos verlos, tocarlos, saborearlos, olerlos u oírlos, los objetos
conceptuales son tan importantes como los objetos físicos en una abstracción general.
Desde una perspectiva de software, un (software)objetoes una construcción/módulo de software que
agrupaestado(datos) ycomportamiento(funciones) que, en conjunto, representan una abstracción de un
objeto del mundo real (físico o conceptual). Esto se ilustra conceptualmente en la Figura 3-4.
CAPÍTULO 3-OBJETOS Y CLASES 69

Figura 3-4.Un objeto de software agrupa estado (datos) y comportamiento (funciones).

Exploremos los dos lados de los objetos (su estado y comportamiento) por separado, con más profundidad.

Estado/Datos/Atributos
Si deseamos registrar información sobre un estudiante, ¿qué datos podríamos requerir? Algunos ejemplos
podrían ser

• El nombre del estudiante

• Su número de identificación de estudiante

• La fecha de nacimiento del estudiante.

• Su dirección

• El principal campo de estudio designado por el estudiante.

• Su promedio de calificaciones acumulativo (es decir, el promedio de calificaciones del estudiante).GPA)

• Quién es el asesor docente del estudiante

• Una lista de los cursos en los que el estudiante está matriculado actualmente en este semestre (es decir, el curso actual del

estudiante).carga académica)

• Un historial de todos los cursos que el estudiante ha tomado hasta la fecha, el semestre/año en el que se tomó
cada uno y la calificación obtenida para cada uno (es decir, la calificación del estudiante).transcripción)

etcétera. Ahora bien, ¿qué tal un curso académico? Quizás querríamos grabar

• El número del curso (p. ej., “ART 101”)

• El nombre del curso (por ejemplo, “Introducción a la cestería”)

• Una lista de todos los cursos que un estudiante debe haber completado con éxito antes de registrarse para
este curso (es decir, el curso del curso).requisitos previos)

• El número de horas de crédito que vale el curso.

• Una lista de los profesores que han sido aprobados para impartir este curso.

etcétera. En la nomenclatura de objetos, los elementos de datos utilizados para describir un objeto se denominan
datos del objeto.atributos.
70 CAPÍTULO 3-OBJETOS Y CLASES

Se dice que los valores de los atributos de un objeto, tomados en conjunto, definen elestado, o
condición, del objeto. Por ejemplo, si quisiéramos determinar si un estudiante es “elegible para
graduarse” (unestado), podríamos considerar una combinación de lo siguiente:

• El expediente académico del estudiante (unvalor de atributo)

• La lista de cursos en los que el estudiante está actualmente matriculado (un segundovalor de atributo)

para determinar si realmente se espera que el estudiante haya satisfecho los requisitos del curso para su
campo de estudio principal elegido (un tercer valor de atributo) al final del año académico actual.
Un atributo determinado puede ser simple, por ejemplo, "GPA", que se puede representar como un
número simple de punto flotante (quizás undobleen Java), o complejo, por ejemplo, “transcripción”, que
representa una colección bastante extensa de información sin una representación simple.

Los programadores nuevos en el paradigma de objetos a menudo preguntan: "¿Por qué no representar una transcripción como un¿Cadena?Alargo

Cadena,sin duda, pero unCadena¿sin embargo?" A lo largo de capítulos sucesivos aprenderá que existe una manera mucho más elegante

de representar la noción de expediente académico de un estudiante en términos orientados a objetos.

Comportamiento/Operaciones/Métodos
Ahora, revisemos los mismos dos tipos de objetos (un estudiante y un curso) y hablemos sobre los comportamientos
respectivos de estos objetos.
Los comportamientos de un estudiante (¡relevantes para asuntos académicos, en cualquier caso!) pueden incluir

• Inscribirse en un curso

• Abandonar un curso

• Designar un campo de estudio importante

• Seleccionar un asesor docente

• Decirnos su GPA

• Decirnos si ha tomado o no un curso en particular y, de ser así, cuándo lo tomó, qué


profesor lo impartió y qué calificación recibió el estudiante.

Es un poco más difícil pensar que un objeto conceptual inanimado como un curso tiene comportamientos,
pero si imagináramos que un curso es un ser vivo, podemos imaginar que los comportamientos de un curso
podrían incluir

• Permitir que un estudiante se registre

• Determinar si un estudiante determinado ya está registrado o no

• Decirnos cuántos estudiantes se han matriculado hasta el momento, o por el contrario, cuántas plazas
quedan antes de que se llene el curso.
CAPÍTULO 3-OBJETOS Y CLASES 71

• Decirnos cuáles son sus cursos previos

• Decirnos cuántas horas de crédito vale el curso.

• Decirnos qué profesor está asignado para impartir el curso este semestre.

etcétera.
Cuando hablamos específicamente de objetos de software, definimos los comportamientos de un objeto, también
conocidos como suoperaciones, como las cosas que un objeto le hace aaccesosus valores de atributos (datos) y las
cosas que un objeto hace paramodificar/mantenersus valores de atributos (datos).
Si nos tomamos un momento para reflexionar sobre los comportamientos que esperamos de un estudiante como se
enumeraron anteriormente, vemos que cada operación involucra uno o más de los atributos del estudiante; Por ejemplo:

• Decirle que su GPA implicaaccediendoel valor del atributo "GPA" del estudiante

• Elegir un campo de estudio importante implicamodificandoel valor del atributo “campo principal de
estudio” del estudiante

• Inscribirse en un curso implicamodificandoel valor del atributo “carga horaria” del estudiante

Como recientemente aprendió que el conjunto colectivo de valores de atributos de un objeto define su estado,
ahora puede ver que las operaciones son capaces decambiar el estado de un objeto. Digamos que definimos el estado
de un estudiante que aún no ha seleccionado un campo de estudio importante como estudiante "no declarado". Pedirle a
un objeto de estudiante que realice su método de "elegir un campo de estudio principal" hará que ese objeto actualice el
valor de su atributo "campo de estudio principal" para reflejar el campo principal recién seleccionado. Esto, entonces,
cambia el estado del estudiante de "no declarado" a "declarado".
Otra forma más de pensar en las operaciones de un objeto es comoserviciosque se puede solicitar del
objeto en nombre de la solicitud. Por ejemplo, un servicio que podríamos pedirle a un objeto de curso que
realice es que nos proporcione una lista de todos los estudiantes que están actualmente registrados en el curso
(es decir, unlista de estudiantes).
Cuando realmente nos dedicamos a programar el comportamiento de un objeto en un lenguaje como Java, nos
referimos a la representación del lenguaje de programación de una operación comométodo, mientras que,
estrictamente hablando, el término “operación” se suele utilizar para referirse conceptualmente a una conducta.

¿Qué es una clase?


Aclasees una abstracción que describe las características comunes de todos los objetos en un grupo de objetos similares. Por
ejemplo, se podría crear una clase llamada "Estudiante" para describir todos los objetos de estudiantes reconocidos por el SRS.

Una clase define

• Elestructura de datos(es decir, los nombres y tipos deatributos) de todos y cada uno de los objetos
pertenecientes a esa clase

• Las operaciones/métodosque deben realizar dichos objetos: específicamente, cuáles son estas
operaciones, cómo se le pide formalmente a un objeto que las realice y qué acciones detrás de
escena debe realizar un objeto para llevarlas a cabo realmente.

Por ejemplo, elAlumnoLa clase podría diseñarse para tener los nueve atributos enumerados en la
Tabla 3-1.
72 CAPÍTULO 3-OBJETOS Y CLASES

Tabla 3-1.Atributos propuestos delAlumnoClase


Atributo Tipo
nombre Cadena

Identificación del Estudiante Cadena

fecha de nacimiento Fecha

DIRECCIÓN Cadena

importante Cadena

gpa doble
tutor ???
carga académica ???
transcripción ???

Tenga en cuenta que muchos de losAlumnoLos atributos se pueden representar mediante tipos simples de Java
predefinidos (p. ej.,Cuerda, doble,yFecha)pero que algunos de los atributos—asesor, carga del curso,y transcripción-son
demasiado complejos para que los manejen los tipos Java integrados. Aprenderá cómo abordar estos atributos un poco
más adelante en el libro.
En términos de operaciones, elAlumnoLa clase podría definir cinco métodos cuyos nombres son los
siguientes:

• registrarse para el curso

• soltarCurso

• elegir mayor

• asesor de cambio

• imprimirTranscripción

Aprenderá cómo declarar formalmente métodos en Java en el Capítulo 4.


Tenga en cuenta que un objeto sólo puede hacer aquellas cosas para las cuales los métodos han sido definidos por
la clase del objeto. En ese sentido, un objeto es como un electrodoméstico: puede hacer cualquier cosa para la cual fue
diseñado (un reproductor de DVD proporciona botones para reproducir, pausar, detener y buscar una escena de película
en particular) y nada más (no se puede preguntar). un DVD para tostar un bagel, ¡al menos no con muchas posibilidades
de éxito!). Entonces, un aspecto importante para diseñar exitosamente un objeto es asegurarse de anticipar todos los
comportamientos que necesitará realizar para llevar a cabo su “misión” dentro del sistema. En la Parte 2 del libro,
aprenderá a determinar formalmente cuál debe ser la misión, la estructura de datos y el comportamiento de un objeto,
en función de los requisitos generales de la aplicación que debe admitir.

El términocaracterísticase usa informalmente para referirse colectivamente tanto a los atributos como a los métodos de
una clase. Es decir, se dice que una definición de clase que incluye nueve declaraciones de atributos y cinco declaraciones de
métodos tiene 14 características.

El término específico de Java para la noción de característica esmiembro. Sin embargo, el término "característica", tal como lo

usaremos informalmente a lo largo del libro y laprecisoEl significado de "miembro" en el sentido de Java no es exactamente lo

mismo. Aplazaremos una discusión en profundidad sobre qué es específicamente un miembro de Java hasta el Capítulo 13.
CAPÍTULO 3-OBJETOS Y CLASES 73

Una nota sobre las convenciones de nomenclatura


Todos los lenguajes de programación orientados a objetos (OOPL), incluido Java, mantienen las siguientes
convenciones de nomenclatura:

• Al nombrar clases, comenzamos con unmayúsculaletra, pero use mayúsculas y minúsculas mixtas para el
nombre en general:Estudiante, Curso, Profesor,etcétera. Cuando lo ideal sería expresar el nombre de una
clase como una frase de varias palabras, como “catálogo de cursos”, comenzamos cada palabra con una
letra mayúscula y concatenamos las palabras sin usar espacios, guiones o guiones bajos para separarlas;
por ejemplo,Catálogo de cursos.Este estilo se conoce comocarcasa pascal.

• La convención para los nombres de atributos y métodos es comenzar con unminúsculasletra, pero para poner en
mayúscula la primera letra de cualquier palabra posterior en el nombre. Por lo tanto, los nombres de atributos típicos
podrían sernombre, ID de estudiante,ocarga académica,mientras que los nombres de métodos típicos podrían ser así
registrarse para el cursoyimprimirTranscripción.Este estilo se conoce comotripa de camello.

Declarar una clase, estilo Java


Una vez que hayamos determinado qué estructura de datos común y comportamientos deseamos impartir a un conjunto de
objetos similares, debemos declararlos formalmente como atributos y métodos en el contexto de una clase Java. Por ejemplo,
programaríamos elAlumnoestructura de datos de clase como se presenta en la Tabla 3-1 de la siguiente manera:

estudiante de clase pública {


// Las declaraciones de atributos suelen aparecer primero en una declaración de clase...
String name;
Cadena ID de estudiante;
Fecha de nacimiento Fecha;

Dirección de cadena;
Cuerda mayor;
doble promedio;

// ¿tipo? asesor: ¡declararemos este atributo en serio más adelante! //


¿tipo? carga del curso - ídem
// ¿tipo? transcripción - ídem

// ... seguido de declaraciones de métodos (se omiten detalles; //


aprenderá a programar métodos en Java en el Capítulo 4).
}

Como ocurre con todas las definiciones de clases Java que has visto hasta ahora en el libro, esta definición de clase
residiría en un archivo fuente llamadoNombre de la clase.java (Estudiante.java,para ser específico) y posteriormente se
compilaría en formato de código de bytes como un archivo llamadoClase.de.estudiante.

Tenga en cuenta que, para que se compile el código anterior, necesitaríamos insertar la declaración

importar java.util.Fecha;

antes de la declaración

Estudiante de clase pública {...}.

discutiremosimportardirectivas del Capítulo 6.


74 CAPÍTULO 3-OBJETOS Y CLASES

Tenga en cuenta que nuestroAlumnoLa clase no está obligada a declarar unaprincipalmétodo. A diferencia de las clases

mostradas anteriormente en el libro, que sirvieron para resumir las características de un programa.principalmétodo

clase pública simple {


público estático vacío principal (String [] argumentos) {
System.out.println("¡¡Me encanta Java!!!");
}
}

elAlumnoLa clase tiene un propósito diferente: es decir, estamos definiendo cuál es la estructura de datos y los
comportamientos deAlumnolos objetos deberían ser.

Creación de instancias
Una definición de clase puede considerarse como una plantilla para crear objetos de software: un "patrón" utilizado
para

• Asigne una cantidad prescrita de memoria dentro de la JVM para albergar elatributosde un nuevo
objeto.

• Asociar un determinado conjunto decomportamientoscon ese objeto.

El términoinstanciaciónse utiliza para referirse al proceso mediante el cual se crea un objeto en la memoria en
tiempo de ejecución según una definición de clase. A partir de una única definición de clase, por ejemplo,Alumno-
Podemos crear muchos objetos con estructuras de datos y comportamientos idénticos, de la misma manera que usamos
un único cortador de galletas para hacer muchas cookies, todas con la misma forma. Otra forma de referirse a un objeto,
entonces, es como uninstanciade una clase particular, por ejemplo, “AAlumnoobjeto es una instancia de laAlumno
clase." (Hablaremos con un poco más de detalle sobre el proceso físico de creación de instancias de objetos tal como
ocurre en Java más adelante en este capítulo).
Por tanto, las clases pueden diferenciarse de los objetos de la siguiente manera:

• Aclasedefine las características (atributos, métodos) que debe poseer cada objeto que pertenece a
la clase; Por lo tanto, se puede considerar que una clase sirve comoplantilla de objeto, como se
ilustra en la Figura 3-5.

Figura 3-5.Una clase prescribe una plantilla para crear instancias de objetos. . .
CAPÍTULO 3-OBJETOS Y CLASES 75

• Unobjeto, por otro lado, es un caso único deplantilla completapara qué valores de atributos
se han proporcionado y sobre qué métodos se pueden realizar, como se ilustra en la Figura
3-6.

Figura 3-6.. . .y luego un objeto completa sus propios valores de atributos únicos.

Encapsulación
Encapsulaciónes un término formal que se refiere al mecanismo que agrupa el estado y el comportamiento
de un objeto en una sola unidad lógica. Todo lo que necesitamos saber sobre un estudiante determinado
está, en teoría, contenido dentro de los límites de unAlumnoobjeto, ya sea

• Directamente, como atributo de ese objeto o

• Indirectamente, como método que puede responder a una pregunta o tomar una determinación sobre el
estado del objeto.

La encapsulación no es exclusiva de los lenguajes OO, pero en algunos sentidos la perfeccionan. Si está
familiarizado con C, sabrá que una Cestructura (ure) encapsula datos:

estructura empleado {
nombre de carácter[30];

edad interna;

y una función C encapsula la lógica: los datos se pasan y se operan con ellos, y opcionalmente se devuelve una respuesta:

promedio flotante (flotante x, flotante y) {


devolver (x + y)/2,0;
}

Pero sólo con los lenguajes de programación OO se adopta verdaderamente la noción de encapsular datos y comportamiento en una

única construcción de clase, para representar una abstracción de una entidad del mundo real.
76 CAPÍTULO 3-OBJETOS Y CLASES

Tipos definidos por el usuario y variables de referencia


En un lenguaje de programación que no sea OO como C, la declaración

intx;

es undeclaraciónesa variableXes unEn t(eger), uno de varios tipos de datos primitivos definidos para ser
parte del lenguaje C. Que haceen realidad¿significar? Esto significa que

• Xes unnombre simbólicoque hemos inventado para referirnos a unEn t(eger) valor que se almacena en algún
lugar de la memoria de la computadora. Sin embargo, no nos importa dónde se almacena este valor, porque

• Siempre que queremos operar con este valor entero particular en nuestro programa, nos referimos a él a
través de su nombre simbólico.X,Por ejemplo:

si (x > 17) x = x + 5;

• Además, la “cosa” que hemos nombradoXentiende cómo responder a una serie de


operaciones diferentes, como suma (+), resta (–), multiplicación (*), división (/),
comparaciones lógicas (>, <, =), etc., según lo definido por elEn ttipo.

En un lenguaje OO como Java, podemos definir una clase comoAlumno,y luego declarar una variable
como de tipoAlumno,como sigue:

Estudiante y;

Que haceen realidad¿significar? Esto significa que

• yes un nombre simbólico que hemos inventado para referirnos a unAlumnoobjeto (es decir, una instancia del
Alumnoclass) que se almacena en algún lugar de la memoria de la computadora. Sin embargo, no nos importa
dónde se almacena este objeto, porque

• Siempre que queremos operar sobre este objeto particular en nuestro programa, nos referimos a él a través de
su nombre simbólico.y,Por ejemplo:

if (y.isOnAcademicProbation()) System.out.println ("Uh oh ...");

• Además, la “cosa” que hemos nombradoyentiende cómo responder a una serie de solicitudes
de servicio diferentes (cómo registrarse en un curso, abandonar un curso, etc.) que han sido
definidas por elAlumnoclase.

Tenga en cuenta los paralelos entreycomo unAlumnoyXcomo unEn ten los ejemplos anteriores. Tal comoEn
tse dice que es untipo predefinidoen Java (y otros lenguajes), elAlumnoSe dice que la clase es unatipo definido
por el usuario. Y porquéyen el ejemplo anterior es una variable quese refiere auna instancia (objeto) de clase
estudiante, añoses conocido como unvariable de referencia.
Por el contrario, las variables declaradas como uno de los ocho tipos primitivos en Java:int, doble,
flotante, byte, corto, largo, char,ybooleano—sonnovariables de referencia, porque en Java, los tipos
primitivos sonnotipos de referencia; es decir, no se refieren aobjetos.

// x NO es una variable de referencia, porque en Java, //


un int NO es un objeto.
intx;
CAPÍTULO 3-OBJETOS Y CLASES 77

// síNo NO es una variable de referencia, porque en Java, // un


valor booleano NO es un objeto.
booleano síNo;

// etc.

Varios lenguajes OO difieren en el tratamiento de tipos simples. En algunos lenguajes OO (por


ejemplo, Smalltalk),todotipos, incluidos los tipos "simples" comoEn tycarbonizarse,son tipos de referencia,
mientras que en otros lenguajes (por ejemplo, Java y C++) no lo son.

El hecho de que Java contenga una combinación de tipos de referencia y tipos sin referencia afecta la forma en que manipulamos

las variables en determinadas circunstancias, como cuando colocamos valores primitivos encolecciones, un tema que

exploraremos en el Capítulo 6. Como discutiremos en el Capítulo 6 y nuevamente en el Apéndice G, las mejoras realizadas al

lenguaje Java a partir de la versión 5.0 disminuyen un poco el impacto de esta diferencia.

Convenciones de nomenclatura para variables de referencia


Los nombres de las variables de referencia siguen la misma convención que los nombres de métodos y atributos, es decir,
utilizan mayúsculas de camello. Algunos ejemplos de declaraciones de variables de referencia son los siguientes:

Requisito previo del curso de este curso;


Profesor Asesor Académico;
Estudiantes;
Estudiante estudiante;

El último de estos,Estudiante estudiante;,Puede que le cueste acostumbrarse si es nuevo en los lenguajes de


programación que distinguen entre mayúsculas y minúsculas. Sin embargo, se considera una buena práctica de
programación crear un patrón de nombres de variables de referencia después del nombre de la clase a la que
pertenecen si solo hay una de esas variables dentro del alcance de un cuerpo de código en particular. Debido a que el
nombre de la clase comienza con una “S” mayúscula y el nombre de la variable de referencia comienza con una “s”
minúscula,Alumnoy alumnosonsímbolos completamente diferentesen lo que respecta al compilador.

Creación de instancias de objetos: una mirada más cercana


Los diferentes lenguajes OO difieren en términos de cuándo se crea una instancia (creación) de un objeto. En Java,
cuando declaramos que una variable es de un tipo definido por el usuario, como en

Estudiante y;

En realidad, todavía no hemos creado un objeto en la memoria. Más bien, simplemente hemos declarado una variable de
referencia de tipoAlumnollamadoy.Esta variable de referencia tiene lapotencialpara referirse a unAlumno objeto, pero
todavía no se refiere a ninguno; más bien, como ocurre con las variables de los distintos tipos simples,tuEl valor de s no
está definido en lo que respecta al compilador hasta que le asignamos explícitamente un valor.
78 CAPÍTULO 3-OBJETOS Y CLASES

Si queremos instanciar unPara estrenarAlumnoobjeto parayPara referirnos, tenemos que dar el paso distintivo de
usar una palabra clave Java especial,nuevo,para asignar un nuevoAlumnoobjeto dentro de la memoria de la JVM en
tiempo de ejecución. Asociamos el nuevo objeto con la variable de referencia.ya través de una declaración de asignación,
de la siguiente manera:

y = nuevo Estudiante();

No se preocupe por los paréntesis al final de la declaración anterior. Hablaré de su significado en el Capítulo 4,
cuando analicemos la noción deconstructores.

Piense en el objeto recién creado como un globo de helio, como se muestra en la Figura 3-7, y en una
variable de referencia como la mano que sostiene una cuerda atada al globo para que podamos acceder al objeto
cuando queramos.

Figura 3-7.Usar una variable de referencia para realizar un seguimiento de un objeto en la memoria

Debido a que a veces se dice informalmente que una variable de referencia "retiene" un objeto, a menudo
usamos el término informalmanejar, como en la expresión “Variable de referenciaymantiene un mango en un
Alumnoobjeto."

Si estás familiarizado con el concepto depunterosEn lenguajes como C y C++, una referencia es similar a un puntero, en el sentido de que

se refiere detrás de escena a la ubicación/dirección de memoria donde se almacena un objeto en particular. Referencias de Javadiferir de

Sin embargo, a partir de punteros, las referencias no se pueden manipular aritméticamente de la misma manera que los punteros.
CAPÍTULO 3-OBJETOS Y CLASES 79

También podríamos crear un nuevo objeto sin asignarlo inmediatamente a una variable de referencia, como
en la siguiente línea de código:

Estudiante nuevo();

pero tal objeto sería como un globo de helio sin una cuerda: de hecho existiría, pero nunca podríamos
acceder a este objeto en nuestro programa. En esencia, “se alejaría flotando” de nosotros en la memoria
inmediatamente después de haber sido “inflado”.
Tenga en cuenta que podemos combinar los dos pasos (declarar una variable de referencia y crear una instancia de
un objeto para que esa variable haga referencia) en una sola línea de código:

Estudiante y = nuevo Estudiante();

Otra forma de inicializar la variable de referencia.yes utilizar una declaración de asignación para
"entregar" yuna referencia a unya existeobjeto: es decir, un objeto (“globo de helio”) al que ya hace
referencia undiferentevariable de referenciaX.Veamos un ejemplo:

// Declaramos una variable de referencia y creamos una instancia de nuestro primer objeto Estudiante.
Estudiante x = nuevo Estudiante();

// Declaramos una segunda variable de referencia, pero *no* instanciamos // un


segundo objeto Student.
Estudiante y;

// Asignamos tu referencia al MISMO objeto al que x se refiere // (x continúa


refiriéndose a él también). Ahora, en esencia,
// tenemos dos "hilos" atados al mismo "globo". y = x;

El resultado conceptual de la tarea anterior se ilustra en la Figura 3-8: dos “cuerdas”,


sostenidas por dos “manos” diferentes, atadas al mismo “globo”, es decir, dosdiferente variables
de referencia referidas a lamismoObjeto físico en la memoria.

Figura 3-8.Mantener múltiples identificadores en el mismo objeto


80 CAPÍTULO 3-OBJETOS Y CLASES

Por lo tanto vemos quemúltiplelas variables de referencia pueden referirse simultáneamente a la


mismo objeto. Sin embargo, cualquierunola variable de referencia solo puede retener/referirse aunoobjeto
a la vez. Por lo tanto, si una variable de referencia ya retiene un objeto, debe soltar ese objeto para hacer
referencia a un objeto diferente. Si llega un momento en que se han liberado todos los identificadores de
un objeto en particular, ese objeto ya no es accesible para nuestro programa, como un globo de helio que
se ha soltado.
Ampliemos nuestro ejemplo anterior para ilustrar estos conceptos (tenga en cuenta elresaltadocódigo que
se ha agregado):

// Declaramos una variable de referencia y creamos una instancia de nuestro primer objeto Estudiante.
Estudiante x = nuevo Estudiante();

// Declaramos una segunda variable de referencia, pero no instanciamos un //


segundo objeto.
Estudiante y;

// Asignamos tu referencia al MISMO objeto al que x se refiere // (x continúa


refiriéndose a él también).
y = x;

// Declaramos una TERCERA variable de referencia y creamos una instancia de un


SEGUNDO // objeto Estudiante.
Estudiante z = nuevo Estudiante();

En este momento, tenemos dos referencias a laprimeroAlumnoobjeto,Xyy,y una referencia,z,


haciasegundoAlumnoobjeto, como se ilustra en la Figura 3-9.

Figura 3-9.Aparece un segundo objeto.

Ampliemos nuestro ejemplo una vez más (tenga en cuenta elresaltadocódigo que se ha agregado):

// Declaramos una variable de referencia y creamos una instancia de nuestro primer objeto Estudiante.
Estudiante x = nuevo Estudiante();
CAPÍTULO 3-OBJETOS Y CLASES 81

// Declaramos una segunda variable de referencia, pero *no* instanciamos // un


segundo objeto.
Estudiante y;

// Asignamos tu referencia al MISMO objeto al que x se refiere // (x continúa


refiriéndose a él también).
y = x;

// Ahora declaramos una tercera variable de referencia y creamos una instancia de un


segundo // objeto Student.
Estudiante z = nuevo Estudiante();

// Reasignamos y para que se refiera al mismo objeto al que se refiere z;


// por lo tanto, y suelta el primer objeto Estudiante y toma el segundo. y = z;

Porque ahora hemos preguntadoypara referirse al mismo objeto quezse refiere, es decir, a lasegundo
Alumnoobjeto-ydebe soltar la manija en elprimeroAlumnoobjeto. Esto se ilustra en la Figura 3-10. (Tenga
en cuenta queXtodavía se aferra a la primeraAlumnoobjeto, sin embargo.)

Figura 3-10.Transferir identificadores de objetos: y suelta al Estudiante n.° 1 para sujetar al Estudiante n.° 2

Ahora completaremos nuestro ejemplo con el código que hemosresaltado:

// Declaramos una variable de referencia y creamos una instancia de nuestro primer //


objeto Estudiante.
Estudiante x = nuevo Estudiante();

// Declaramos una segunda variable de referencia, pero *no* instanciamos // un


segundo objeto.
Estudiante y;
82 CAPÍTULO 3-OBJETOS Y CLASES

// Asignamos tu referencia al MISMO objeto al que x se refiere // (x continúa


refiriéndose a él también).
y = x;

// Ahora declaramos una tercera variable de referencia y creamos una instancia de un


segundo // objeto Student.
Estudiante z = nuevo Estudiante();

// Reasignamos y para que se refiera al mismo objeto al que se refiere z. y = z;

// Reasignamos x para que se refiera al mismo objeto al que se refiere


z. // x por lo tanto suelta el primer objeto Estudiante y se agarra //
también al segundo.
x = z;

Porque ahora hemos preguntadoXpara referirse al mismo objeto quezse refiere, es decir, a lasegundo
Alumnoobjeto-Xdebe soltar la manija en elprimeroAlumnoobjeto. Dado que ya no mantenemos
ninguna referencia al primerAlumnoobjeto cualquiera—x, y,yzahora todos se refieren a lasegundo-la
primeraAlumnoEl objeto ahora se pierde en el programa, como se ilustra en la Figura 3-11.

Figura 3-11.La primeraAlumnoEl objeto ahora se pierde en nuestro programa.

Otra forma de hacer que una variable de referencia libere su identificador en un objeto es establecer la variable de
referencia en el valornulo,que, como comentamos en el Capítulo 2, es la palabra clave de Java utilizada para representar
un objeto inexistente. Siguiendo con nuestro ejemplo anterior

• ConfiguraciónXanuloobtieneXpara soltar su manija en el segundoAlumnoobjeto, como se ilustra en la


Figura 3-12.

x = nulo;
CAPÍTULO 3-OBJETOS Y CLASES 83

Figura 3-12.En el segundo solo quedan dos asas.Alumnoobjeto.

• Configuraciónyanuloobtieneypara soltar su manija en el segundoAlumnoobjeto, como se ilustra en la


Figura 3-13.

x = nulo;
y = nulo;

Figura 3-13.En el segundo solo queda un asa.Alumnoobjeto.


84 CAPÍTULO 3-OBJETOS Y CLASES

• Lo mismo ocurre conz,como se ilustra en la Figura 3-14.

x = nulo;
y = nulo;
z = nulo;

Ahora,ambosAlumno¡Se han perdido objetos en nuestro programa!

Figura 3-14.El segundoAlumnoEl objeto ahora también se pierde en nuestro programa.

Recolección de basura
Resulta que si se liberan todos los identificadores de un objeto, podría parecer que la memoria que ocupa el
objeto dentro de la JVM se desperdiciaría permanentemente. En un lenguaje como C++, esto puede suceder si los
programadores no se preocupan explícitamente de recuperar la memoria de un objeto que ya no es necesario
antes de que se eliminen todos sus identificadores. No hacerlo es una fuente crónica de problemas en los
programas C++ y se conoce comúnmente comopérdida de memoria.

En C++, esto se logra mediante la siguiente declaración:

x.eliminar();

pero tal declaración es innecesaria en Java, por razones que vamos a discutir.

Con Java, por otro lado, la JVM realiza periódicamenterecolección de basura, un proceso que
recupera automáticamente la memoria de los objetos “perdidos” mientras se ejecuta una aplicación. Así es
como funciona el recolector de basura de Java:
CAPÍTULO 3-OBJETOS Y CLASES 85

• Si no quedan referencias activas a un objeto, se convierte en uncandidatopara la recolección de


basura.

• El recolector de basura noinmediatamentereciclar el objeto, sin embargo; más bien, la


recolección de basura ocurre cada vez que la JVM determina que la aplicación se está
quedando sin memoria libre o cuando la JVM está inactiva.

• Por lo tanto, durante un período de tiempo, el objeto “huérfano” seguirá existiendo en la memoria; simplemente
no tendremos ningún identificador/variable de referencia con el que acceder a él.

Tenga en cuenta que hay una manera de solicitar explícitamente que se realice la recolección de basura en Java mediante la siguiente declaración:

Runtime.getRuntime().gc();

Incluso entonces, sin embargo, el momento preciso decuandoLa recolección de basura ocurre está fuera del control del

programador, al igual que cuáles y cuántos objetos elegibles se recolectarán.

La inclusión de la recolección de basura en Java prácticamente ha eliminado las pérdidas de memoria del
tipo que surgieron en C++. Tenga en cuenta que aún es posible que la JVM se quede sin memoria si mantenemos
identificadores en demasiados objetos activos simultáneamente. Por tanto, un programador de Java no puede
ignorar por completo la gestión de la memoria; La gestión de la memoria es menos propensa a errores en Java
que en C/C++.

Objetos como atributos


Cuando hablé por primera vez de los atributos y métodos asociados con elAlumnoclase, dije que algunos de los
atributos podrían representarse mediante tipos predefinidos proporcionados por el lenguaje Java, mientras que
los tipos de algunos otros (asesor, carga del curso,ytranscripción)quedaron temporalmente sin especificar. Ahora
hagamos un buen uso de lo que hemos aprendido sobre los tipos definidos por el usuario con respecto a uno de
estos atributos: elAlumnoclasetutoratributo.
En lugar de declarar latutoratributo como simplemente unCadenaque representa el nombre del
asesor, lo declararemos como de tipo definido por el usuario, es decir, tipoProfesor,Otra clase que hemos
inventado. Este tipo de atributo se refleja en la Tabla 3-2.

Tabla 3-2.Atributos de la clase estudiantil revisados

Atributo Tipo
nombre Cadena

Identificación del Estudiante Cadena

fecha de nacimiento Fecha

DIRECCIÓN Cadena

importante Cadena

gpa doble
tutor Profesor
carga académica ???
transcripción ???
86 CAPÍTULO 3-OBJETOS Y CLASES

También se refleja en nuestra declaración de clase de Estudiante:

estudiante de clase pública {


// Las declaraciones de atributos suelen aparecer primero...
String name;
Cadena ID de estudiante;
Fecha de nacimiento Fecha;

Dirección de cadena;
Cuerda mayor;
doble promedio;

// Una clase es un tipo definido por el usuario, por lo que podemos declarar
atributos // como de ese tipo.
Profesor asesor;
// ¿tipo? courseLoad: declararemos este atributo más adelante. //
¿tipo? transcripción – ídem.

// ... seguido de declaraciones de métodos (detalles omitidos por ahora).


}

Al haber declarado latutoratributo para ser de tipoProfesor-es decir, al tener la tutoratributo sirve
comovariable de referencia—acabamos de habilitar unAlumnoobjeto para mantener un control sobre la
situación realProfesorObjeto que representa al profesor que está asesorando al alumno.
ElProfesorLa clase, a su vez, podría definirse para que tenga los atributos enumerados en la Tabla 3-3.

Tabla 3-3.Atributos de la clase estudiantil

Atributo Tipo
nombre Cadena

ID de empleado Cadena

fecha de nacimiento Fecha

DIRECCIÓN Cadena

trabaja para Cadena (oDepartamento)

aconsejado Alumno

enseñanzaAsignaciones ???

Nuevamente, al haber declarado laaconsejadoatributo para ser de tipoAlumno-es decir, haciendo el


aconsejadoatribuir una variable de referencia: acabamos de dar unaProfesorobjeto una manera de aferrarse a/
referirse a lo realAlumnoObjeto que representa al estudiante a quien el profesor está asesorando.
Los métodos de laProfesorclase podría ser la siguiente:

• transferiraldepartamento

• aconsejarEstudiante

• aceptar enseñar curso

• asignar calificaciones

Etcétera.
CAPÍTULO 3-OBJETOS Y CLASES 87

Tal como lo hicimos con elAlumnoclase anteriormente en el capítulo, renderizaríamos estoProfesordiseño de clase en
código Java de la siguiente manera:

Profesor de clase pública {


// Atributos.
Nombre de cadena;

Id. de empleado de cadena;

Fecha de nacimiento Fecha;

Dirección de cadena;
La cadena funciona para;

Estudiante asesorado;
doble promedio;

// ¿tipo? TeachingAssignments: declararemos este atributo más adelante.

// ... seguido de declaraciones de métodos (detalles omitidos por ahora).


}

Esta definición de clase residiría en un archivo fuente llamadoProfesor.java,y posteriormente se compilaría


en formato de código de bytes como un archivo llamadoProfesor.clase.

Tenga en cuenta que, como se mencionó anteriormente para elAlumnoclase, necesitaríamos insertar la declaración

importar java.util.Fecha;

antes de la declaración

Profesor de clase pública {...}

para que el código se compile correctamente. Hablaremos sobre el tipo de fecha de Java en el Capítulo 13.

A continuación se presentan algunos puntos dignos de mención sobre laProfesorclase:

• Es probable que un profesor esté asesorando a varios estudiantes simultáneamente, por lo que
tener un atributo comoestudianteAsesoradoque puede hacer referencia sólo a unsolteroAlumno
objeto no es muy útil. Discutiremos técnicas para manejar esto en el Capítulo 6, cuando analicemos
colecciones, que también veremos como útil para definir elenseñanzaAsignacionesatributo de
Profesor,y elcarga académicaytranscripciónatributos deAlumno.

• Eltrabaja paraEl atributo representa el departamento al que está asignado un profesor. Podemos elegir
representar esto como un simpleCadenaque representa el nombre del departamento, por ejemplo,
"MATH", o como una variable de referencia que mantiene un identificador en unDepartamento objeto—
específicamente, elDepartamentoobjeto que representa el Departamento de Matemáticas del “mundo
real”. Por supuesto, para hacerlo sería necesario definir los atributos y métodos para una nueva clase
llamadaDepartamento.

Como discutiremos más adelante en la Parte 2 de este libro, la decisión de si necesitamos o no inventar
un nuevo tipo/clase definido por el usuario para representar un concepto/abstracción particular del
mundo real no siempre es clara.
88 CAPÍTULO 3-OBJETOS Y CLASES

Un truco de compilación: clases de “apagado”


Si quisiéramos programar elAlumnoyProfesorclases en Java, como se mostró anteriormente, ninguna de ellas se
puede compilar de forma aislada; es decir, si simplemente escribiéramos el código para elAlumnoclase:

// Estudiante.java

estudiante de clase pública {


// Las declaraciones de atributos suelen aparecer primero...
String name;
Cadena ID de estudiante;
Fecha de nacimiento Fecha;

Dirección de cadena;
Cuerda mayor;
doble promedio;

Profesor asesor;
// etc.
}

sin haber escrito aún el código para elProfesorclase (Profesor.java),obtendríamos un error de


compilación enAlumnocomo sigue:

Student.java: no se puede encontrar el


símbolo símbolo: clase Ubicación del
profesor: clase Estudiante
Profesor asesor;
^

porque aún no lo hemos definido”Profesor"como tipo para el compilador de Java.


Podríamos esperar hasta que hayamos programado tanto elAlumnoyProfesorclases antes de
intentar compilar cualquiera de ellas, pero ¿qué pasaría si introdujéramos una tercera clase en la mezcla?

estudiante de clase pública {


Nombre de cadena;

Profesor asesor;
Departamento mayor;
// etc.
}

Profesor de clase pública {


Nombre de cadena;

Estudiante asesorado;
Trabajos del departamentoPara;

// etc.
}
CAPÍTULO 3-OBJETOS Y CLASES 89

Departamento de clase pública {


Nombre de cadena;

Profesor presidente;
// etc.
}

¿O una cuarta clase, o una quinta? ¿Debemos programar?todode ellos antes de compilar cualquieruno¿de ellos?
Afortunadamente podemos utilizar la técnica de“apagando”una clase para solucionar temporalmente problemas
relacionados con la compilación de una clase X que hace referencia a una clase Y, que aún no hemos programado.
Volviendo a nuestroAlumnoclase como se escribió originalmente

// Estudiante.java

estudiante de clase pública {


// Las declaraciones de atributos suelen aparecer primero...
String name;
// etc.
Profesor asesor;
// etc.
}

podemos codificar temporalmente un "básico"Profesorclase de la siguiente manera:

// profesor.java

// Una clase "stub": ¡tenga en cuenta que el cuerpo consta de un par de llaves vacías!
Profesor de clase pública { }

Tan trivial como estoProfesorLa definición de clase puede ser, no obstante, se considera unalegítimo definición de clase
por parte del compilador de Java que, cuando se compila, producirá unProfesor.clasearchivo de código de bytes.

Cuando ahora intentamos compilar nuestroEstudiante.javaarchivo, el compilador efectivamente considerará


"Profesor"ser un símbolo válido (específicamente, el nombre de un tipo definido por el usuario) yAlumnotambién se
compilará correctamente.

Recuerde que podemos compilar elEstudiante.javayProfesor.java (“stub”) archivos simultáneamente con el


comando único

javac*.java

Eso es,profesor.javaNo es necesario compilarlo por separado primero.

Composición
Cada vez que creamos una clase, comoAlumnooProfesor,en el que uno o más de los atributos son en sí mismos
referencias a otros objetos, estamos empleando una técnica OO conocida comocomposición. El número de
niveles en los que se pueden agrupar conceptualmente los objetos unos dentro de otros es infinito, por lo que la
composición nos permite modelar conceptos muy sofisticados del mundo real. Resulta que la mayoría de las
clases "interesantes" emplean composición.
90 CAPÍTULO 3-OBJETOS Y CLASES

Con la composición, conceptualmente puede parecer que estamos anidando físicamente objetos uno dentro
de otro, como se muestra en la Figura 3-15.

Figura 3-15.Objeto conceptual “anidado”

El anidamiento real de objetos (es decir, declarar una clase dentro de otra) es posible en
muchos lenguajes de programación OO y, de hecho, a veces tiene sentido, es decir, si un
objeto A no necesita tener vida propia desde el punto de vista de una aplicación OO, y existe
sólo con el propósito de servir al objeto adjunto B.

• Piense en su cerebro, por ejemplo, como un objeto que existe sólo dentro del contexto de su
cuerpo (otro objeto).

• Como ejemplo de anidamiento de objetos relevante para el SRS, consideremos un libro de calificaciones utilizado para
realizar un seguimiento del desempeño de los estudiantes en un curso en particular. Si tuviéramos que definir unLibro
de calificacionesclase y luego crearLibro de calificacionesobjetos como atributos: uno porCursoobjeto—entonces podría
ser razonable para cadaLibro de calificacionesobjeto existe enteramente dentro del contexto de sus asociados. Curso
objeto. Ningún otro objeto necesitaría comunicarse con elLibro de calificacionesdirectamente; si unAlumnoobjeto
deseaba preguntar unCursoobjetar qué gradoAlumnoha ganado, el CursoEl objeto podría consultar internamente su
contenido incrustado.Libro de calificacionesobjeto y simplemente entregue una letra de calificación alAlumno.

De hecho, ilustraremos la noción deLibro de calificacionescuando discutimosclases internasen el Capítulo 13.

Sin embargo, a menudo nos encontramos con la situación –como en el caso de la muestraAlumnoyProfesorclases en las
que un objeto A necesita hacer referencia a un objeto B, el objeto B necesita hacer referencia nuevamente al objeto A, y
ambosLos objetos deben poder responder a las solicitudes de forma independiente entre sí tal como las realiza la
aplicación en su conjunto. En tal caso, ¡las manijas vienen al rescate!
En realidad, lo hacemosnoalmacenar objetos completos como atributos dentro de otros objetos; más bien, almacenamos
referenciasa los objetos. Cuando un atributo de un objeto A se define en términos de una referencia de objeto B,
CAPÍTULO 3-OBJETOS Y CLASES 91

Los dos objetos existen por separado en la memoria y simplemente tienen una forma conveniente de
encontrarse cuando es necesario que interactúen. Piensa en ti mismo como un objeto y en tu número de
teléfono móvil como referencia. Otras personas (“objetos”) pueden comunicarse con usted a través de su
número de teléfono celular para hablar con usted cuando lo necesiten, aunque no sepan dónde se
encuentra físicamente; y por el contrario, si tienes sus números de celular, puedes llamarlos cuando
quieras.
La asignación de memoria mediante identificadores podría parecerse conceptualmente a la Figura 3-16.

Figura 3-16.Los objetos existen por separado en la memoria y mantienen identificadores entre sí.

Con este enfoque, cada objeto se asigna en la memoria sólo una vez:

• ElAlumnoEl objeto sabe cómo encontrar y comunicarse con su asesor (Profesor) objeto
siempre que lo necesite a través de sututoratributo/identificador/referencia.

• ElProfesorEl objeto sabe cómo encontrar y comunicarse con su destinatario (Alumno) objeto
siempre que lo necesite a través de suaconsejadoatributo/identificador/referencia.

Aprenderá cómo codificar realmente dicha intercomunicación de objetos en Java en el Capítulo 4.

Las ventajas de las referencias como atributos


¿Qué ganamos al definir laAlumno'stutoratributo como referencia a unProfesorobjeto, en lugar de
simplemente almacenar el nombre del asesor como unCadenaatributo de laAlumno¿objeto?Evitamos la
redundancia de datos y la posible pérdida asociada de integridad de los datos.. Veamos cómo funciona
esto.
Encapsulando el nombre de cada profesor dentro del correspondienteProfesorobjeto, cada nombre estará
representado en un solo lugar dentro de una aplicación: a saber,dentro del objeto al que pertenece el nombre,
cual esprecisamente¡a donde pertenece! (Aprenderá en el Capítulo 4 cómo preguntarle a unProfesorobjeto para
su nombre siempre que necesite saberlo). Luego, si el nombre de un profesor determinado cambia por algún
motivo, solo tenemos una copia de ese nombre para cambiar en nuestra aplicación, el nombre que está
encapsulado dentro del archivo correspondiente.Profesorobjeto.
Si en cambio tuviéramos que diseñar nuestra aplicación de manera que almacenáramos de forma
redundante elProfesor's nombre tanto comoCadenaatributo de laProfesorobjeto y comoCadenaatributo de cada
Alumnoobjeto que aconseja el profesor, ¡tendríamos mucho más trabajo por hacer! Tendríamos que recordar
92 CAPÍTULO 3-OBJETOS Y CLASES

actualizar el nombre del profesor no sólo en elProfesorobjeto, pero también en potencialmente muchos
diferentesAlumnoobjetos. Si nos olvidáramos de actualizar todos esos objetos, entonces el nombre del
Profesorpodría terminar siendo inconsistente de unoAlumnoinstancia a otra.
Igual de importante es mantener el control sobre elProfesorobjeto a través deltutoratributo de
Alumno,elAlumnoobjeto también puedesolicitar otros serviciosde estaProfesorobjeto a través de
cualquier método definido para elProfesorclase. Además de pedir la asesoría del asesor (Profesor's)
nombre, unAlumnoobjeto puede, por ejemplo, preguntar a su asesor (Profesor)objeto donde elProfesor'
dónde está ubicada la oficina, o qué cursosProfesorestá enseñando para que elAlumnoPuedes inscribirte en
uno de ellos.
Una última ventaja de utilizar referencias a objetos desde el punto de vista de la implementación es que también reducen
la sobrecarga de memoria. Almacenar una referencia a (también conocida como dirección de memoria de) un objeto solo
requiere 4 bytes (en máquinas de 32 bits) u 8 bytes (en máquinas de 64 bits) de memoria, en lugar de la cantidad de bytes de
almacenamiento que ocupe el objeto al que se hace referencia en su conjunto. en memoria. Si tuviéramos que hacer una copia
de un objeto completo en todos los lugares donde necesitáramos hacer referencia a él en nuestra aplicación, podríamos agotar
rápidamente la cantidad total de memoria disponible para la JVM.

Tres características distintivas de un lenguaje de


programación orientado a objetos
Para ser considerado verdaderamente orientado a objetos, un lenguaje de programación debe brindar soporte
para tres mecanismos clave:

• Tipos definidos por el usuario (referencia)

• Herencia

• Polimorfismo

Acaba de conocer el primero de estos mecanismos; Discutiremos los otros dos en los
capítulos siguientes.

Resumen
En este capítulo has aprendido que

• Unobjetoes una abstracción de software de un objeto físico o conceptual del mundo real.

• AclaseSirve como plantilla para crear objetos. Específicamente, una clase define (a) los datos que
encapsulará un objeto, conocidos como datos del objeto.atributos, y (b) los comportamientos/
servicios que un objeto podrá realizar, conocido como operaciones de un objeto/métodos.

• Un objeto puede considerarse comoinstanciade una clase a cuyo atributovaloreshan sido


asignados—en esencia, unrellenadoplantilla.

• Así como podemos declarar variables como de tipos primitivos comoint, doble,ybooleano, También
podemos declarar variables como detipos definidos por el usuariocomoAlumnoyProfesor. Los tipos
definidos por el usuario se declaran como clases.
CAPÍTULO 3-OBJETOS Y CLASES 93

• Cuando creamos un nuevo objeto en tiempo de ejecución (un proceso conocido comoinstanciación),
normalmente almacenamos una referencia a ("manejar") ese objeto en unvariable de referencia. Luego
podemos usar la variable de referencia como un nombre simbólico para acceder y comunicarnos con el objeto.

• Podemos definir atributos de una clase A para que sirvan como referencias a objetos que pertenecen a otra clase
B. Al hacerlo, permitimos que cada objeto encapsule la información que pertenece legítimamente a ese objeto,
pero permitimos que los objetos se encuentren entre sí en la memoria en tiempo de ejecución para que puedan
comunicarse entre sí para compartir información cuando sea necesario.

Ejercicios

1.Desde la perspectiva de un entorno académico (pero no necesariamente del estudio de caso de SRS específicamente),
piense cuáles podrían ser los atributos y métodos apropiados de las siguientes clases:
• Aula
• Departamento
• Grado

2.[Codificación] Renderizar elAlumnoyProfesorclases como se presentan en este capítulo en código Java. Al hacerlo, (a)
omitir declaraciones de métodos, (b) declarar cualquierFechaatributos para ser de tipoCadenaen cambio.
Finalmente, crea una tercera clase llamadaClase principalservir como “envoltorio” para unprincipalmétodo que
instancia uno Alumnoobjeto y unoProfesorobjeto.

3.[Codificación] Revise el código que escribió para el ejercicio 2 anterior para incluir una tercera clase,Departamento; declarar lo

que seaDepartamentoLos atributos parecen razonables pero, una vez más, omita las declaraciones de métodos por ahora.

Luego, regresa y modifica elimportanteatributo deAlumnopara referirse a unDepartamento,y el trabaja paraatributo de

Profesorpara referirse a unDepartamento.Finalmente, modifique elClase principal'sprincipal método para crear una

instancia de unDepartamentoobjeto junto con unAlumnoy unProfesor.

4.Para el área del problema cuyos requisitos definió para el ejercicio 3 en el Capítulo 1, enumere las clases que podría
necesitar crear para modelarla adecuadamente.

5.Enumere las clases que podría necesitar crear para modelar el Sistema de seguimiento de recetas (PTS) que se
analiza en el Apéndice B.

6.haríaColor¿Ser un buen candidato para un tipo/clase definido por el usuario? ¿Por qué o por qué no?

También podría gustarte