Programacion en Java 2
Programacion en Java 2
fflrJ
PROGRAMACIÓN EN JAVA 2
h l'so...Ci.?...
t' A1 o~ 2.. --:r-<r/'K
Este trabajo se publica con el reconocimiento expreso de que se está proporcionando una
información, pero no tratando de prestar ningún tipo de servicio profesional o técnico.
Los procedimientos y la información que se presentan en este libro tienen sólo la intención
de servir como guía general.
McGraw-Hill ha solicitado los permisos oportunos para la realización y el desarrollo de esta obra.
McGraw-Hm / lnteramericana
de España S. A. U.
DERECHOS RESERVADOS© 2005, respecto a la primera edición en español, por
McGRAW-HILL/INTERAMERICANA DE ESPAÑA, S. A. U.
Edificio Valrealty, 1ª planta
Basauri, 17
28023 Aravaca (Madrid)
www.mcgraw-hill.es
[email protected]
ISBN: 84-481-4591-7
Depósito legal: M. 24.998-2005
A mi mujer, Paqui
y a mis hijos, Femando, Carmen y Raquel.
GHFT
A mis padres.
PMD
Introducción a la programación ••••• ••• •••• ••... •••••• •••.. ••• •• •••• •... 9
1.1 Estructura de un programa.................................................................... 9
1.2 Identificadores ... .. ...... .. ..... ............... ... .......... ........ .................... ... .. .. ...... 1O
1.3 Tipos, variables y valores .. ................ ...................... ................... ........ .. 11
1.4 Expresiones........................................................................................... 13
1.5 Conversiones de tipo ............................................................................. 15
1.6 Enumerados........................................................................................... 15
l. 7 Petición de valores primitivos al usuario .............................................. 16
Problemas resueltos ...................... .. .......................................... ............ ............. 17
CAPÍTULO 8 Interfaces 1111111m1111111m111111 ill lllllll 111. 111111u1111111111 Slil 11111111111111111lll11111111DIII11111111 • • • • • • 11!1 !11 • ••••••• 11111 • • • • • • • • • l!l:$1911:illll& 2-7,5
8.1 Definición y uso de interfaces ............................................................... 275
Problemas resueltos .... ........ ....... ........................................................................ 278
CAPÍTULO 9
9.1 Genéricos .............................................................................................. 301
9 .2 Definición de genéricos ........ ............ ............... ...................................... 301
9 .3 Herencia de genéricos y conversión de tipos ......................................... 302
9.4 Comodines............................................................................................. 302
9.5 Métodos genéricos................................................................................. 303
Problemas resueltos .... ............ ............ ............................................................... 305
'" La sencillez y elegancia de cómo se escriben los programas en Java. A ello se une que es un lenguaje orientado
a objetos que evita muchas preocupaciones a los programadores. En el proceso de compilación se realizan
multitud de comprobaciones que permiten eliminar muchos posibles errores posteriores.
'" Las bibliotecas ya definidas que proporciona el lenguaje y que el programador puede utilizar sin tener que
hacerlas de nuevo.
La evolución de Java ha sido muy rápida. Desde que se hizo público el lenguaje y un primer entorno de desarrollo,
el JDK (Java Development Kit), hasta el momento actual, la plataforma Java ha ido creciendo constantemente y a un
ritmo cada vez mayor según se han ido incorporando un gran número de programadores de todo el mundo.
Pero Java 2 no es sólo un lenguaje. Es una plataforma de desarrollo de programas que consta de:
La plataforma Java2 se puede utilizar desde distintos sistemas operativos, ejecutándose cada uno de ellos en el
hardware correspondiente. (Véase Figura 0.1.)
Programación en Java 2
Java
Sistema de ejecución
(runtime) API
Máquina virtual
Sistema operativo
(Solaris, Linux, Windows, Macos, ... )
Hardware
(Sparc, Pentium, PowerPC, ... )
.. Edición del programa fuente. Se denomina programa fuente al programa que se escribe utilizando un entor-
no de programación como los descritos, o cualquier editor, en un lenguaje de programación. En Java los
archivos fuentes tienen un nombre como nombre.java, donde el nombre ha de ser el mismo que el empleado
como nombre de la clase y la extensión ha de ser .java.
.. Compilación. Tras escribir el programa hay que compilarlo utilizando un compilador. Los entornos de desa-
rrollo facilitan esa tarea, haciéndola casi invisible en alguno de ellos. También se puede compilar utilizando la
línea de comandos con la herramienta javac, de la siguiente forma: javac nombre.java.
En el proceso de compilación se comprueba que lo que se ha escrito es correcto en Java y se traducy a otro
lenguaje, denominado código de bytes (bytecode). Si durante la compilación se detectan errores, el entorno
avisará de los problemas detectados y dónde se han encontrado para que pueda corregirlos. Si en la compila-
ción no se detecta ningún error se genera un archivo como nombre.class, con el mismo nombre que la clase
que se compila pero con la extensión .class.
" Ejecución. Una vez compilado se ejecuta el programa y se comprueba si hace lo que se había previsto. Si el
programa no hace lo previsto se vuelve a editar, modificando los aspectos que no funcionan adecuadamente.
Que viene a indicar la importancia relativa que debe conceder a estos tres aspectos en la programación:
111 Legibilidad: El programa ha de ser fácil de leer y entender, incluso para una persona que no haya participado
en el desarrollo del programa. Este aspecto es en la actualidad el más importante. A pesar de lo que pueda
pensar en este momento, dar legibilidad a un programa hará que los otros aspectos salgan ganando.
111 Corrección: Un programa debe hacer lo que tiene que hacer, ni de más, ni de menos. Se supone que con la fase
de pruebas se comprueba hasta cierto nivel que es cierto y que el programa funciona correctamente.
• Eficiencia: Suele ser una preocupación típica de muchos programadores. La eficiencia se suele medir en
tiempo que se tarda en ejecutar o en cantidad de memoria que ocupa el programa. Nuestro consejo es que se
olvide completamente de este tema. Una vez domine el lenguaje ya tendrá tiempo de ocuparse de ello.
En el Apéndice B puede encontrar recomendaciones específicas para mejorar la legibilidad de un programa y, por
tanto, debería conocerlas y seguirlas lo máximo posible. Siempre que pueda fíjese en cómo escriben los programas los
buenos programadores.
Dada la extensión del libro, no se describirán otros aspectos de los entornos de programación. Tenga en cuenta
también, que los entornos que aquí se describen son las últimas versiones disponibles de los programas en el momen-
to final de entrega del libro manuscrito.
Dada la evolución de los entornos es fácil que la versión actualizada que usted pueda encontrar ya haya variado.
Sin embargo, esperamos que le siga siendo útil esta presentación.
"'l
~------~--~.J
l'rlljectli/)O;l!lroí j::\DocumsntsandSe~~ 1 !lr!;tw$e... 1
[s doolmsntos. . 91!lj.-!
~~~~~.l'r;Q¡eá
@~~~<;l¡¡oo !~'is:~¡;;;-··--···--·--··- ··---·]
/U
" 8pe.rarn arg:s the .::orm.1:!tlld l1n.e l:l.rgw,i,ento
•1
pülic :ita.U.e: 't'Oid ma1n (String[] m:gs) (
Systcm.out.)llr:lntln("tiotu de Progr~1ón"l;
S7:rto.out.11rint("Nota del pri?m!!r parcial: "I:
Sr,,te:ia.out.print.ln(4.5):
Syatem.out.pr:lnt("Nota del :segundo pe.retal: "):
Sr,,tem.out.11rintl.n(7 .SJ;
Sy:stem.out.print("Nota ttnal: "):
Sr,,tem.0ut.J1riniln(6):
A continuación, en la ventana siguiente introduzca en el campo de texto Project Name el nombre del proyecto, por
ejemplo Notas. Tras generar el proyecto pulse Finish para terminar.
Una vez generado el proyecto aparece en la parte derecha del entorno de desarrollo la información del proyecto.
Para crear la clase inicial del programa seleccione, pulsando con el botón derecho del ratón sobre el nombre del
proyecto, la opción New -> Class, y en la ventana que aparece rellene los campos Name, con el nombre de la clase, por
ejemplo Notas y marque la casilla de verificación para crear el método public static void main(), tal como aparece en
la Figura 0.5.
Una vez aparezca el código fuente generado complételo como aparece en el Figura 0.6. Para ejecutarlo seleccione
el icono verde con una flecha hacia la derecha. Le aparecerá una ventana de configuración de la ejecución la primera
vez. En ella seleccione en la parte derecha Java Aplication, seleccione en el modo Run la opción Java y haga doble clic
en Java Aplication para, por último hacer doble clic en Notas.java. Las siguientes veces ya guarda esta configuración
y basta con hacer clic en el icono verde de ejecución.
/O
* ?pi.%illl<"\ ar9s
•/
publi.c static voi.d main{String{] args) f
system.out.println(,.Notas de Pt:e>gramaci6n");
system.out.print{"Nota del primer parcial: "
system .out.println (4.5);
system.out.print("Nota del segundo parcial:
system.out.println n .5);
System.out.print(,.Mota final: ");
System.out.println(ó);
Figura 0.7. Pantalla de creación de una nueva clase, interface, enumerado, etc.
¿Qué es Java?
.,
• Ovt.u1cn (4 vt.r::1<:m. mooei: ce a lh.~J
1c cl.u:r Xous (
publ1c 9to.tic void "111(.Str:irl.9[] u:qs) (
Systea.wt.p.r:1ntln .("'!OtM d'1: Pr:o,¡r&¾a':U·n")J
1'ystt::!l.cut,l)únt. rl'Jota dtl p-rlvAt V{lrt1,i<,1: ");
SfSttihO\&t,pc1nU Dl4,S): .
~cut.pu.M.C"'! t"'t<l <td ; ¡ : ~ p&.u:t-'111: .. ,J
~~t..p'timl11. (1.S);
sy.,ta.cuc,prtnt("t t1>tll !11:.'.':ll~ ");
Sp«111;,out.p1:1m. lu!61;
Project TemplalB
@~
Project Cia!ISPalh
ProjectTools
Aparece entonces la ventana principal como la de la Figura 0.9. Haga doble clic en el nombre del programa
Notas.java y borre lo que no necesite del código que aparece en la ventana de trabajo. Pulse el botón de
compilar y
después el de ejecutar (como se ha marcado en la Figura 0.10). Al ejecutar el programa aparece una ventana
con el
resultado de la ejecución.
'l
3
4
5
/H
8l
,i: fl/
7 8 pub lle class Notas {
publlc stat1c vo1d main(String[J ar¡¡s) {
$ System.out.pr intln("Notas de Programación" );
10 System.out.pr 1nt("Nota del primer parcial: ");
11 System.out.p rintln(4.5),
12 System.out .pr1nt ( "Nota del segundo parcial: ")
l;! System.out.pr intln(7 .5);
14 System.out.pr 1nt("Nota final: ");
lS System.out.p rintln(6);
16
17 }
18
/**
* Programa en Java que escribe un texto en la pantalla.
*/
public class Hola {
public static void main(String[J args) {
System.out.println("Hola a todos.");
En este programa se pueden ver algunos de los elementos que se van a utilizar siempre que se escribe un programa
en Java:
• Comentario. El programa empieza con un comentario. El comentario del programa empieza con /** y acaba
con*/.
• Defmición de clase. La primera línea del programa después del comentario def'me una clase que se llama
Ho l a. La definición de la clase empieza en el carácter abre llave { y termina en el carácter cierra llave }. Todo
lo encerrado entre las llaves defme el bloque de la clase.
• Definición de método. A continuación, se escribe el método ma in ( ) • Todos los programas en Java deben tener
un método ma in ( ) , que se escribe de la misma forma que el del ejemplo.
• Sentencias. Dentro del método ma i n( ) , en el bloque delimitado por abre llave y cierra llave, existe una única
sentencia o instrucción que escribe un texto por pantalla.
Para ver el resultado de ejecutar este programa, utilice el entorno de programación que haya elegido de la forma
descrita en la documentación del mismo. Tenga en cuenta que en Java las letras mayúsculas y las letras minúsculas
son letras distintas, por lo que debe escribirlas tal como aparecen en el ejemplo dado.
Programación en Java 2
/**
* Estructura de una clase en Java
*/
public class NombreOeClase {
/! Declaración de los atributos de la clase
En el caso de ser una clase distinta de la clase principal, el método ma i n( ) no suele aparecer.
Se han puesto como comentarios (que empiezan por dos barras) los elementos que suelen componer una clase, que
son los siguientes:
., Atributos de la clase. Son las variables que definen el estado de los objetos. Se tratarán con detalle en el
Capítulo 2. Puede pensar en ellos como variables definidas en el bloque de la clase.
,. Declaración de métodos. Son fragmentos de código que hacen una determinada función. Se tratarán con
detalle en el Capítulo 2.
., El método principal main(). Ya se ha visto en el primer ejemplo. Dentro de este método se escribe lo que se
desea que ejecute el programa, ya que siempre se empieza a ejecutar este método .
., Declaración de variables. Se verán en las siguientes secciones .
., Sentencias. Es la parte que se ejecuta en el programa. Ya se ha visto en el primer ejemplo un programa con
una sentencia para escribir un texto en la pantalla. Las sentencias se ejecutan siempre en el orden en el que se
escriben y, siempre, una detrás de otra, hasta que se acaba el método ma in ( ) .
1.2 IDENTIFICADORES
Un identificador es un nombre. Los nombres permiten identificar los elementos que se están manejando en un
programa. Existen reglas estrictas sobre cómo se pueden escribir los nombres de las clases, las variables, métodos,
etc. Cualquiera de estos nombres debe ser un identificador. Un identificador debe empezar con una letra y debe
seguir una sucesión de letras y dígitos.
Una letra es cualquier carácter que se considera una letra en Java. Como en Java se utiliza Unicode para los
caracteres, un identificador se puede escribir con caracteres hebreos, cirílicos, armenios, katakana, etc. Para formar
un identificador también se consideran letras los caracteres subrayado '_' y dólar '$', aunque el carácter'$' práctica-
mente no se suele utilizar, salvo en algún tipo de nombrado automático. Se considera un dígito a cualqnier carácter
entre los caracteres 'O' a '9'. De esta forma son válidos los siguientes identificadores:
Aunque de acuerdo con la regla anterior serían válidos, sin embargo, no lo son los identificadores que coincidan
con una palabra reservada del lenguaje (tenga cuidado porque final es una palabra reservada).
Cuando elija un identificador, siga las siguientes recomendaciones:
qué
" Debe utilizar nombres que sean significativos, de forma que cuando lo vea escrito sepa para qué sirve y de
tipo va a ser sin necesidad de acudir a su declaración.
, cada
" Los nombres de variables y métodos empiezan con minúscula. Si se trata de un nombre compuesto
de otras. Ejemplos de
palabra empieza con mayúscula. No se utiliza el carácter subrayado para separar unas
nombres de variables o métodos: n, númeroElementos, ponValor, escribeTít ulo.
empieza
" Los nombres de clases empiezan con mayúscula. Si se trata de un nombre compuesto, cada palabra
con mayúscula. No se utiliza el carácter subrayado para separar unas de otras. Ejemplos de nombres de clases:
VolumenCilindro,Alumno,ProgramaDePrueba .
carácter
., Los nombres de constantes se escriben en mayúsculas. Si el nombre es un nombre compuesto utilice el
subrayado para separar unos de otros. Ejemplos de nombres de constantes: PI, TAMAÑ0_MÁ XIM0.
double radio:
va a
Con ello se declara que va a existir en el programa una variable con el nombre radio y que esa variable
del programa poniendo su
guardar un valor del tipo doub le. Una vez declarada se puede utilizar en cualquier lugar
nombre. Siempre que se utilice el nombre de una variable es como si pusiese el valor que tiene.
forma:
Si se quiere guardar un valor en una variable, se utiliza el operador de asignación de valor de la siguiente
radio= 23.4:
desee. El
Donde se indica el nombre de la variable, el carácter igual (=), y cualquier expresión o cálculo que se
símbolo igual significa lo siguiente: haz el cálculo de la expresión que se encuentra a la derecha del igual y, después,
guarda el valor calculado en la variable que hay a la izquierda. Si después se ejecuta:
radio= 44.56:
la variable radio guarda el valor 44.56. El valor anterior se pierde en esa variable.
Programación en Java 2
El valor de una constante no se puede modificar en el programa, por eso hay que darle un valor a la vez que se
declara.
Los tipos primitivos que se pueden utilizar para declarar variables, y los intervalos de valores de cada uno de ellos,
se pueden ver en la Tabla 1.1.
• Números enteros. Permiten representar números enteros positivos y negativos con distintos intervalos de valores.
• Números reales. Permiten guardar valores con decimales con distinta precisión.
., Caracteres. Existe un tipo carácter (char) que permite representar cualquier carácter Unicode.
• Booleano. Es un tipo que indica un valor lógico. Sólo tiene dos valores, verdadero (true) y falso (false).
Otro tipo muy utilizado es para los textos o cadenas de caracteres. En realidad se trata de objetos, que se verán con
detenimiento en los Capítulos 2 y 3, pero se pueden utilizar de forma sencilla como si fueran variables de tipos
primitivos.
Stri ng texto;
texto= "En un lugar de la mancha de cuyo nombre ... ";
Literales
Números enteros
Los números enteros se pueden escribir de tres formas:
Si se escribe un valor del tipo long se le debe añadir detrás el carácter 'l' o 'L' (una letra ele minúscula o
mayúscula).
Introducción a la programación
Números reales
Para escribir valores reales en Java, se puede hacer de las siguientes formas: le2, 2., .54, 0.45, 3.14, 56.34E-45. Es
decir, un número real en Java siempre tiene que tener un punto decimal o un exponente indicado por la letra e
minúscula o la letra E mayúscula.
Si no se indica nada se supone que pertenecen al tipo doub 1e. Si se desea que se interpreten como del tipo float se
debe añadir un carácter 'f' o 'F' detrás del valor de la siguiente forma: le2f, 2.f, .54f, 0.45f, 3.14f. Se puede añadir el
carácter 'd' o el carácter 'D' para indicar explícitamente que el valor es del tipo doub 1e, de la siguiente forma: 4.56d,
78.34e-4d.
Booleanos
Los valores del tipo boo lean sólo pueden ser dos, true y fa 1se, y se escriben siempre en minúsculas.
Caracteres
Los valores del tipo carácter representan un carácter Unicode. Un carácter siempre se escribe entre comillas simples.
Un valor carácter se escribe como 'a', 'Z', 'Ñ', ';', '1t', etc., o por su código de la tabla Unicode, en octal o en
hexadecimal. Por ejemplo: '\u00A3', en hexadecimal o '\102' en octal.
Existen algunos caracteres especiales como los que se indican en la Tabla 1.2.
\b Retroceso
\t Tabulador
\n Salto de línea
\r Cambio de línea
\" Carácter comillas dobles
\' Carácter comillas simples
\\ Carácter barra hacia atrás
1.4 EXPRESIONES
Sobre cada uno de los tipos de valores se pueden utilizar un conjunto de operadores para formar expresiones o
cálculos.
Números enteros
Al realizar una operación entre dos números enteros el resultado siempre es un entero.
• Unarias: poner un signo más o un signo menos delante. Por ejemplo: +44, -56.
• Multiplicativas: * multiplica dos valores, / divide el primer valor entre el segundo, y % calcula el resto de la
división entera. Ejemplos: 4 * 5, 8 / 2, 5 % 2.
• Aditivas(+,-): La suma y la resta de la forma usual. Ejemplo: 4 + 5
• Incremento y decremento(++, - -): Incrementa el valor en uno y decrementa el valor en uno de una variable.
Los operadores de incremento y decremento se pueden poner antes o después de la variable que se desea
incrementar o decrementar.
., Relación(>,>= ,<, <=): Permiten comparar valores. El resultado de una operación con los operadores de
relación es un valor boo 1ean indicando si es cierta o falsa la relación.
.. Operadores de igualdad(=, !=): Comparan si dos valores son iguales o son distintos. El resultado es un valor
del tipo boolean, indicando si es cierta o no la igualdad o desigualdad.
., Operadores de asignación(=,+ =,-=,*=,/=,%=) : El primero es el operador de asignación ya descrito y el resto
son operadores que permiten simplificar la escritura de expresiones muy comunes.
Programación en Java 2
Números reales
Con los números reales se pueden realizar las mismas operaciones que con números enteros. En el caso de las
operaciones unarias, aditivas o multiplicativas el resultado de la operación con números reales es un número real.
También se pueden utilizar los operadores de relación e igualdad cuyo resultado es un valor del tipo boo lean.
Booleanos
Los operadores sobre booleanos son los siguientes:
Precedencia de operadores
Toda expresión se evalúa a un valor de una forma estricta. El cómo se evalúa una expresión depende del orden de
prioridad de los operadores que contenga dicha expresión. De forma simplificada el orden de prioridad y la forma de
evaluación es:
1. Operadores unarios.
2. Operadores multiplicativos, de izquierda a derecha.
3. Operadores aditivos, de izquierda a derecha.
4. Operadores de relación.
5. Operadores de asignación.
a= -3 + 5 + 2 * 4 - 6 / 4 * 3 - 5 %2:
(D@(z) ® ® ® ©® ®
evalúa la expresión de acuerdo al orden indicado debajo de la misma. De esta forma primero se aplica el operador
unario a 3 para obtener el valor -3. A continuación se van evaluando los operadores multiplicativos de izquierda a
derecha, 2 * 4 se evalúa a 8, 6 / 4 se evalúa a 1 que multiplicado por 3 se evalúa a 3 y 5 % 2 se evalúa a l. En este
momento la expresión queda:
a= -3 + 5 + 8 - 3 - 1:
Por último, se evalúan los operadores aditivos de izquierda a derecha, siendo el resultado final de 6. Este es el
valor que se guarda en la variable a.
Si se desea que la evaluación se realice en un orden específico, se deben utilizar paréntesis. En una expresión
siempre se empieza a evaluar por los paréntesis más internos.
Expresiones aritmético-lógic as
Una expresión aritmético-lógica es una expresión que devuelve un valor booleano donde se utilizan operadores
aritméticos y operadores relacionales y de igualdad. Una expresión aritmético-lógica podría ser la que sigue y su valor
es true, pues es cierto que 8 es menor que 10:
(3 + 5) < (5 * 2)
Introducción a la programación
En una expresión aritmético-lógica se pueden combinar varias expresiones sencillas de las anteriores mediante
los operadores lógicos. La precedencia de los operadores booleanos es menor que la de los operadores relacionales,
por lo que primero se evalúan las desigualdades y después los operadores booleanos. El orden de prioridad entre los
operadores booleanos es: la negación, después el Y lógico y, por último, el O lógico. La prioridad de los operadores de
asignación es la menor de todas. Por tanto, en la expresión:
se evalúa primero las expresiones aritméticas y después las relacionales, quedando la expresión
En realidad se evalúa en primer lugar la primera expresión a true, para, como el operador es 11, evaluar la
expresión completa a true.
1. 5 CONVERSIONES DE TIPO
En muchas ocasiones resulta necesario realizar algunas conversiones de tipos, de forma que el resultado sea del tipo
esperado. Para convertir valores entre tipos existen dos formas:
.. Conversión automática de tipos. Cuando el tipo al que se asigna un valor es "mayor'', la conversión se realiza
automáticamente. Así un valor de tipo doub le se puede multiplicar por otro del tipo i nt. Antes de hacer la
multiplicación se convierte el valor i nt a doub le y luego se hace la multiplicación entre reales .
., Conversión explícita. Se pone delante del valor a convertir, entre paréntesis, el tipo al que se desea convertir.
Como esta conversión suele implicar una pérdida de valor, hay que tener mucho cuidado. Por ejemplo ( i nt) 34. 45,
hace una conversión a un tipo i nt, trunca el valor y se pierden los decimales.
En la conversión de tipos existe un tipo especial de expresiones que involucra a los valores del tipo char. Un
tipo cha r siempre se puede utilizar en una expresión junto con números enteros como si fuese un número entero
más:
char e = 'A":
int n;
n =e+ 2:
1.6 ENUMERADOS
Los enumerados son conjuntos de valores constantes para los que no existe un tipo predefinido. Por ejemplo, no existe
ningún tipo predefinido para representar los días de la semana, las estaciones del año, los meses del año, los turnos de
clases, etc.
Para definir un tipo enumerado con sus valores se haría de la siguiente forma:
/**
* Programa en Java que pide al usuario los datos
* del radio y la altura de un cilindro y calcula su volumen
*/
import java.util.Scanner;
public class PedirDatos {
public static void main(Stríng[J args)
// El valor del numero pi
final double PI= 3.1415926536;
double radio;
double altura:
System. out. pri nt ln(" Introduzca los datos del ci 1indro: ");
.print("Radio: ");
"Altura:");
En la primera línea marcada se declara un objeto de la clase Scanner. Ya verá en el Capítulo 2 qué es un objeto y
cómo se utiliza. De momento, piense que la variable teclado va a ser un objeto que nos va a permitir leer los datos que
se escriben por el teclado. En la segunda línea marcada, cuando el programa la ejecuta se queda esperando a que el
usuario escriba algo en el teclado y pulse la tecla de retorno. En ese momento convierte lo leído en un valor del tipo
doub l e y lo guarda en la variable radio. Igual ocurre con la tercera línea marcada para leer un valor para la altura. Si
lo que desea es leer otro tipo de datos hágalo como se indica en la Tabla 1.3.
Introducción a la programación
byte teclado.nextByte();
short teclado.nextShort();
int teclado.nextint();
long teclado.nextlong();
float teclado.nextFloat();
double teclado.nextDouble();
boolean teclado.nextBoolean();
Ejercicio 1.1:
Escriba un programa que escriba en la pantalla su nombre completo en una línea y en la línea siguiente su
fecha de nacimiento.
Planteamiento: Para escribir este programa se va a utilizar el esquema básico donde la clase tiene el nombre
Mi sDatosPersona les (fíjese en las mayúsculas y minúsculas). Dentro del bloque del ma in () se utilizarán dos
sentencias para escribir en pantalla, una para el nombre y otra para la fecha de nacimiento. Ambos datos se
escribirán como textos entre comillas dobles.
Solución:
public class MisDatosPersonales
public static void main(String[J args) {
System.out.println("José Juan Juárez Juárez"); <Cí¿----11
Para escribir un texto se pone entre
comillas dobles.
System.out.println("l2/12/1977");
Comentarios: Se utiliza System. out. pri nt l n() para escribir un texto y pasar a la línea siguiente.
Ejercicio 1.2:
Escriba un programa que imprima en la pantalla su nombre completo en una línea y en la línea siguiente su
fecha de nacimiento. Para ello escriba una sentencia para escribir el nombre, otra sentencia para escribir su
primer apellido y otra para escribir su segundo apellido.
Planteamiento: Se va a escribir un programa de nombre Mi sDatosPersona l es2 que escriba el nombre, que se
hará sin cambiar de línea, a continuación escriba el primer apellido sin cambiar de línea y, después, el segundo
apellido y cambie de línea. Para terminar escribe la fecha de nacimiento.
Solución:
public class MisDatosPersonales2 {
Programación en Java 2
Ejercicio 1.3:
Escriba un programa que escriba en pantalla las notas de la asignatura de "Programación". En la primera
línea se escribirá el nombre de la asignatura. En las siguientes líneas se escribirán las notas de los dos
parciales realizados poniendo la nota de cada uno en líneas distintas. En la última línea escribirá la nota
final de la asignatura. Escriba lo que sea texto como un texto entre comillas dobles y lo que sea un número
como un número.
Planteamiento: Se va a escribir un programa de nombre Mi sNotas que escriba los textos tal y como se ha
hecho en los ejercicios anteriores. Para escribir las notas se utilizará la misma sentencia pero poniendo entre
paréntesis el número de la nota. Hay que tener cuidado porque en Java los números con decimales utilizan el
punto decimal.
Solución:
public class Notas
public static void main(String[] args) {
System. out. pri ntl n( "Notas de Programación"):
System.out.print("Nota del primer parcial: ");
System.out.println(4.5);4~------------11 Para los decimales hay que utilizar
el punto decimal.
System.out.print("Nota del segundo p9rcial: ");
System.out.println(7.5);
System.out. print( "Nota final: ");
System.out.println(6);
IDENTIFICADORES
Ejercicio 1.4:
Dados los siguientes identificadores que se van a utilizar en un programa escrito en Java, diga cuáles de ellos
son correctos y cuáles no. Justifi.que su respuesta.
a) mi carta
b) unacarta
c) mis2escritos
d) 4cientos
e) es_un_mensaje
f) no_vale nada
g) _ _ejemplo _ __
h) mi-programa
i) ¿cuantos?
j) el%Descontado
k) al50PORHORA
l) TengoMUCHOS$$$
Introducción a la programación
m) LOS400GOLPES
n) quieroUNAsolución
Planteamiento: Hay que tener en cuenta que un identificador sólo puede estar formado por letras y dígitos y
que debe comenzar exclusivamente por una letra.
En Java también se consideran letras los caracteres subrayado y $, aunque este último se utiliza sólo de forma
especial.
Solución:
a)No es correcto. pues tiene un espacio en medio.
b)Es correcto. pues está formado sólo por letras.
c)Es correcto. pues está formado por letras y tiene un dígito en medio.
d)No es correcto. pues comienza por un dígito y eso no es válido.
e) Es correcto. pues está formado sólo por letras. ya que el carácter subrayado se considera
también como una letra.
f) No es correcto. pues tiene un espacio en medio.
g) Es correcto. pues el carácter subrayado se considera una letra. Por tanto. el identificador
está formado sólo por letras.
h) No es correcto. pues el carácter guión no se considera una letra ni un dígito.
i) No es correcto. pues los caracteres de abre interrogación y cierra interrogación no se
consideran letras ni dígitos.
j) No es correcto. pues el carácter tanto por ciento no se considera una letra ni un dígito.
k) Es correcto. pues está formado por letras y tiene dígitos en medio.
l) Es correcto. pues el símbolo$ se considera también una letra.
m) Es correcto. pues está formado por letras y tiene dígitos en medio.
n) Es correcto, pues está formado sólo por letras.
Ejercicio 1.5:
Dados los siguientes identificadores que se van a utilizar en un programa escrito en Java, diga cuáles de ellos
son correctos y cuáles no. Justifique su respuesta.
a) descarta2
b) cuántosQuerrás
c) Carr3Mesas
d) raVaBienAvec$$
e) Égresa
f) osterreich
g) Nosyevan
h) EsaCziMÉceJEóoouuyOÜrfJ[(J)
Solución:
a) Es correcto. pues está formado sólo por letras y acaba en un dígito.
b) Es correcto. pues está formado sólo por letras.
c) Es correcto. pues está formado sólo por letras y un dígito en medio.
d) Es correcto. pues está formado sólo por letras. ya que la c con cedilla es una letra y el
carácter$ se considera una letra.
e) Es correcto. pues está formado sólo por letras. ya que la E tal como está acentuada es una letra.
f) Es correcto. pues está formado sólo por letras. ya que la o con diéresis es una letra.
g) Es correcto. pues está formado sólo por letras. ya que la y con diéresis es una letra.
h) Es correcto. pues está formado sólo por letras.
Programación en Java 2
Ejercicio 1.6:
Escriba un programa que escriba en la pantalla cuánto le costará comprar unas deportivas cuyo precio de
catálogo es de 85,00 €, si sabe que puede conseguir una rebaja del 15%.
Planteamiento: Hay que realizar el cálculo de 85,00€ menos el 15%, para ello se utiliza la fórmula (85*(1-
0,15)). Hay que tener cuidado, pues en Java los números con decimales utilizan el punto decimal. Se llamará
al programa CompraZapati 11 as.
Solución:
public class CompraZapatillas
public static void main(String[J args) {
System.out.print(85.00 * (1 - 0.15)): 11-~----~1
Se utiliza el punto decimal para los
números reales.
Comentario: Al ejecutar el programa en la pantalla aparece 72. 25, cuyo valor también se puede calcular como
(85 * 0.85).
Ejercicio 1.7:
Escriba un programa que escriba en la pantalla cuánto le dará su banco después de seis meses si pone 2000€ en una
cuenta a plazo fijo al 2, 75% anual. Recuerde que al pagarle los intereses el banco le retendrá el 18% para hacienda.
Planteamiento: Hay que realizar el cálculo de 2000€ al 2,75%, es decir, los intereses son 2000*2,75/100/2, ya
que seis meses es ½ del año. De esos intereses le retienen el 18%, por lo que realmente el banco le pagará
2000*2,75/100/2 * (1-0,18).
Solución:
public class Calculolntereses
public static void main(String[J args)
System.out.print(2000*2.75/100/2 * (1-0.18)): +- Se utiliza el punto decimal para los
números reales.
Aviso: En la expresión se han mezclado números reales y números enteros. Por tanto, se está haciendo una conver-
sión automática de tipos, convirtiendo todos los valores a reales y haciendo las operaciones entre números reales.
Ejercicio 1.8:
Escriba un programa que escriba en la pantalla cuánto le dará su banco después de seis meses si pone 2000€
en una cuenta a plaza fijo al 2, 75% anual. Recuerde que al pagarle los intereses el banco le retendrá el 18%
para hacienda. Escriba los mensajes apropiados para entender todos los cálculos.
Planteamiento: Hay que realizar el cálculo de 2000€ al 2,75%, es decir, los intereses son 2000*2,75/100/2, ya
que seis meses es ½ del año. De esos intereses le retienen el 18%, por lo que realmente el banco le pagará
2000*2,75/100/2 * (1-0,18).
Solución:
public class Calculolntereses
1.ntroducclón a Da programación
Aviso: Hay que tener cuidado al realizar cálculos e imprimirlos. Si se hubiese realizado una suma en lugar de
un producto y se hubiese escrito:
La suma de 2 + 2 vale: 22
Es decir, los operadores + se evalúan de izquierda a derecha, por lo que se concatena el texto con el primer 2,
y el resultado es un texto. A continuación se concatena el texto con el segundo 2, pues hay otra operación+,
dando como resultado La suma de 2 + 2 vale: 22. Sin embargo, si se escribe:
como el operador* tiene mayor precedencia que el operador+, en primer lugar se evalúa el operador*, por lo que
2*2 se evalúa a 4. A continuación, se evalúa la concatenación del texto con el 4, escribiendo, por tanto, en pantalla:
El producto de 2 + 2 vale: 4
Para escribir correctamente la suma de 2 + 2 hay que escribir la expresión aritmética entre paréntesis:
Ejercicio 1.9:
Dadas las siguientes expresiones aritméticas, calcule cuál es el resultado de evaluarlas.
a) 25 + 20-15
b) 20 * 10 + 15 * JO
c) 20*10/2-20/5*3
d) 15 I 10 * 2 + 3 I 4 * 8
Planteamiento: Para cada una de las expresiones anteriores hay que tener en cuenta la precedencia de los
operadores. Como sólo constan de operadores aditivos y multiplicativos se harán primero los multiplicativos
de izquierda a derecha y luego los aditivos de izquierda a derecha. Hay que tener en cuenta también que como
todos los números son números enteros el resultado de todas las operaciones serán números enteros.
Solución:
a) 25 + 20-15
Se realizan las operaciones de izquierda a derecha, pues son todas aditivas:
25 + 20 - 15 = 45 - 15 = 30
Programación en Java 2
b) 20 * 10 + 15 * 10
Se realizan primero las operacione s multiplicativas de izquierda a derecha:
20 * 10 + 15 * 10 = 200 + 15 * 10 = 200 + 150
Después se realiza la operación de suma
200 + 150 = 350
c) 20 * 10 / 2- 20 / 5 * 3
Se realizan primero las operacione s multiplicat ivas de izquierda a derecha:
20 * 10 / 2 - 20 / 5 * 3 = 200 / 2 - 20 / 5 * 3 = 100 - 20 / 5 * 3 = 100 - 4 * 3 = 100 - 12
Después se realiza la operación de sustracción
100-12= 88
d) 15 / 10 * 2 + 3 / 4 * 8
Se realizan primero las operacione s multiplicativas de izquierda a derecha:
15 / 10 * 2 + 3 / 4 * 8 = 1 * 2 + 3 / 4 * 8 = 2 + 3 / 4 * 8 = 2 + O * 8 = 2 + O
Después se realiza la operación de suma
2+0=2
ello, en el
Comentari os: Hay que recordar que las operacione s entre valores enteros siempre son enteros. Por
apartado d) 15/10 se evalúa a 1 y, de la misma forma, 3/4 se evalúa a O.
Ejercicio 1.10:
Dadas las siguientes expresiones aritméticas, calcule cuál es el resultado de evaluarlas. Suponga que las
variables a y b que aparecen son del tipo i nt y a tiene el valor 2 y b tiene el valor 4.
a) -a + 5 % b - a * a
b) 5 + 3 % 7 * b * a-b % a
c) (a+l)*( b+l)-bl a
Planteamiento: En cada una de las expresione s anteriores, cuando sea necesario el valor sustituye la variable
en cuenta
por su valor. En el cálculo hay que tener en cuenta la precedenci a de los operadores. Hay que tener
enteros el resultado de todas las operacione s serán números
también que como todos los números son números
enteros.
Solución:
a) -a+ 5 % b - a * a
Antes de operar se va realizando la sustitución de valores
(se
Primero se evalúa la operación unaria del signo - delante de la variable a. El- 2 se evalúa al valor -2
representa por un signo menos más pequeño)
-2+5% 4-2*2= ~+5%b -a*a
Después se evalúan las operacione s multiplicativas de izquierda a derecha
-2 + 5 % b - a * a= -2 + 5 % 4 - a * a = -2 + 1 - a * a = -2 + 1 - 2 * 2 = -2 + 1 - 4
Por último se evalúan las operacione s aditivas de izquierda a derecha
-2+ 1-4=-l- 4 =-5
b) 5+3%7 *b*a-b% a
Se evalúan las operacione s multiplicativas de izquierda a derecha
5 + 3 % 7 * b * a-b % a =5 + 3 * b * a- b % a =5 + 3 * 4 * a-b % a =5 + 12 * a- b % a =5 +
12 *
2-b % a =5 + 24-b % a=5 +24-4 % 2 =5 +24-0
Por último se evalúan las operacione s aditivas de izquierda a derecha
5 + 24 - O = 29 - O = 29
c) (a+ 1) * (b + 1) - b / a
En primer lugar se evalúan las expresione s entre paréntesis
(2 + 1) * (b + 1) - b /a= 3 * (b + 1) - b /a= 3 * (4 + 1) - b / a = 3 * 5 - b / a
Introducción a la programación
Comentarios: Cuando en una expresión hay expresiones entre paréntesis, en primer lugar se evalúan los
paréntesis más internos.
Ejercicio 1.11:
Escriba un programa que defina dos variables enteras para describir las longitudes de los lados de un
rectángulo. El programa debe calcular y escribir en la pantalla las longitudes de los lados, el perímetro y el
área del rectángulo. (Suponga que el rectángulo mide 15cm de alto y 25cm de ancho.)
Planteamiento: Se necesita declarar dos variables para guardar los valores de los lados. Como se dice que los
lados son números enteros, las variables se declaran del tipo i nt. Para realizar los cálculos se van a declarar
dos variables más, una para el cálculo del perímetro y otra para el cálculo del área. Finalmente, se imprimirán
por pantalla todos los datos y resultados de los cálculos.
Solución:
public class Rectangulo
public static void main(String[] args) {
int alto= 15:
int ancho= 25:
Comentarios: Fíjese en los nombres elegidos para las variables. Es importante que se entienda bien para qué sirve
cada valor. Fíjese también en la estructura del programa: primero la declaración de variables y valores iniciales, un
segundo bloque de cálculos a partir de las variables y un tercer bloque de presentación de resultados. Tanto la elección
de nombres como la estructura utilizada facilitan seguir el programa y entender lo que hace fácilmente. Imagínese la
diferencia si las variables se hubiesen llamado a, b, e y d. Sería casi imposible saber para qué sirve el programa.
Ejercicio 1.12:
Escriba un programa para calcular el área y el volumen de un cilindro. Para ello declare una constante que
guarde el valor de 1r. Declare, también, variables para el diámetro y la altura del cilindro. Suponga para el
ejemplo que el cilindro tiene un diámetro de 15,5cm y una altura de 42,4cm.
Planteamiento: Se necesita declarar dos variables para guardar los valores del diámetro y la altura del cilin-
dro, que debe ser del tipo doub le. Además, hay que declarar una constante para el valor de x. El cálculo del
área y el volumen se realiza con las fórmulas clásicas para ello.
Solución:
public class AreaVolumenCilindro
Programación en Java 2
Comentario: Para utilizar el número PI podría haberse utilizado el que ya está definido en la biblioteca
matemática. Para ello basta sustituir PI en las fórmulas por Math. PI (consulte en el Capítulo 2 cómo hacerlo).
Quizá el número de decimales que resulta al escribir los valores no sea el más apropiado. Puede dar un formato
más apropiado, con sólo dos decimales, utilizando el siguiente fragmento de código:
Además pri ntf() realiza una localización de los datos de forma que los números reales aparecen escritos con
coma decimal como se hace habitualmente. El % significa que a continuación aparecerá una definición de
formato. La expresión %.2f significa escribe un número real con dos dígitos después de la coma. En el mismo
punto del texto donde se escribe esa definición de formato se escribirá el valor de la variable que aparece a
continuación. El carácter \n al final del texto en el método printf() es el carácter de fm de línea.
Ejercicio 1.13:
Escriba un programa que escriba en la pantalla cuánto le dará su banco después de seis meses si pone 2000€
en una cuenta a plaza fijo al 2,75% anual. Recuerde que al pagarle los intereses el banco le retendrá el 18%
para hacienda. Utilice variables para manejar las cantidades y realizar los cálculos. Escriba los mensajes
apropiados para entender todos los cálculos.
Planteamiento: Para el cálculo se necesitarán variables para guardar el dinero a invertir (doub l e), el tipo de
interés anual (double) y el número de meses de la inversión (int). Como el tipo de retención que se aplica es
fijo se declarará como una constante de tipo double (pues pudiera ser un número no entero). También se
utilizará una constante que guarde el número de meses que tiene el año.
Solución:
public class Calculointereses
public static void main(String[] args) {
final double RETENCIÓN= 18;
final int mesesAño = 12:
System.out.println("Cálculo de intereses.");
System.out.printf("Dinero ingresado: %.2f€.\n", capitallnvertido);
System.out.printf( "Interés anual: %.2f%%. \n". interésAnual); &=====""""'"""'"'""'""""'"""'""""'""""'
System.out .printf("Intereses a los %d meses: %.2f€. \n". ~~---1i Seimprimendosvaloresenorden
de aparición.
mesesinversión. interesesObtenidos):
System.out.printf("Retención realizada: %.2f€. \n". retención);
System.out.printf("Intereses cobrados: %.2f€.\n". interesesCobrados);
Comentario: Para escribir valores monetarios resulta muy apropiado el uso de printf() (impresión con
formato) pues permite decidir que se desean imprimir sólo dos decimales. El formato %d indica escribir
un número entero y %f, un número real. Si aparece una definición de formato (siempre empieza con%),
se sustituye cada una de ellas por las variables que se pongan a continuación separadas por comas en el
mismo orden de aparición. Los tipos de los valores deben coincidir con el formato indicado para ellos.
Como % indica el principio de definición de formato, si se desea escribir el signo % hay que ponerlo dos
veces.
EXPRESIONES ARITMÉTICO-LÓGICAS
Ejercicio 1.14:
Dadas las siguientes expresiones aritmético-lógicas calcule cuál es el resultado de evaluarlas.
Planteamiento: Para cada una de las expresiones anteriores hay que tener en cuenta que se trata de expresio-
nes aritméticas junto con operaciones de comparación y operaciones relacionales. De acuerdo con la preceden-
cia de las operaciones habrá que realizar las operaciones en el siguiente orden: operaciones aritméticas, opera-
ciones relacionales y, por último, operaciones booleanas. Las operaciones booleanas tienen la siguiente
precedencia: primero la negación, después el y-lógico(&&) y, por último, el o-lógico (11).
Solución:
a) 25 > 20 && 13 > 5
Se realizan las operaciones de relación
25 > 20 && 13 > 5 = true && 13 > 5
Como la parte izquierda del y-lógico(&&) vale true hay que evaluar la parte de la derecha:
true && 13 > 5 = true && true
Ahora se evalúa el &&
true && true = true
. Programación en Java 2
Ejercicio 1.15:
Dadas las siguientes expresiones aritmético-lógicas calcule cuál es el resultado de evaluarlas. Suponga que
las variables a y b que aparecen son del tipo i nt y a tiene el valor 5 y b tiene el valor 3.
Planteamiento: En cada una de las expresiones anteriores se sustituye la variable por su valor cuando se vaya a
utilizar. En el cálculo hay que tener en cuenta la precedencia de los operadores. Hay que tener en cuenta también
que como todos los números son números enteros el resultado de todas las operaciones serán números enteros.
Solución:
a) !(a> b && 2 * a<= b)
En primer lugar se evalúa la parte entre paréntesis. Para ello se evalúa primero la parte izquierda del
operador&&
!(a> b && 2 *a<= b) = !(5 > 3 && 2 *a<= b) = !(true && 2 *a<= b)
Introducción a la programación
Como la parte izquierda del operador && vale true, hay que evaluar su parte derecha
!(true && 2 *a<= b) = !(true && 2 * 5 <= 3) = !(true && 10 <= 3) = !(true && false)
De donde evaluando los operadores booleanos
!(true && false)= !(false)= true
b) b++ > 311 a+ b <= 8 && !(a> b)
Esta expresión se evalúa de izquierda a derecha. Como tiene mayor prioridad el operador && que el
operador II se evalúa como si estuviese escrito (el 11 (e2 && e3)), por tanto se evalúa el y si su valor es
false se evalúa la parte derecha del operador 11, por ello
b++ > 3 11 a+ b <= 8 && !(a> b) = 3 > 3 11 a+ b <= 8 && !(a> b) =false II a+ b <= 8 && !(a> b)
Además, al evaluar b++, b se incrementa en 1 pasando a valer 4. Como la parte izquierda de la expresión
vale false hay que evaluar la parte derecha. Se comienza entonces por la parte izquierda del operador &&
false II a+ b <= 8 && !(a> b) =false 115 + 4 <= 8 && !(a> b) = false 119 <= 8 && !(a> b) = false 119 <=
8 && !(a> b) = false II false && !(a> b)
Como la parte izquierda del operador && vale false ya no es necesario evaluar la parte derecha
false II false && !(a > b) = false II false = false
c) a++< 6 && (b += 2) < a
Esta expresión sólo tiene un operador boolean &&. Por tanto, se evalúa en primer lugar su parte izquierda
a++ < 6 && (b += 2) < a= 5 < 6 && (b += 2) < a= true && (b += 2) < a
y el valor de la variable a se incrementa en 1 a 6. A continuación se evalúa la parte derecha del operador
&&. (b += 2) añade a b el valor 2 y devuelve el valor resultado de la asignación
true && (b += 2) < a= true && (5) < a= true && 5 < 6= true && true= true
El resultado final es true y las variables a y b han quedado con los valores a = 6 y b = 5
d) a++/ 2 < b && (a++/ 2 > b 11 (a* 2 < b * 4))
Esta expresión consta de un operador booleano (&&) entre dos expresiones, por lo que en primer lugar se
evalúa su parte izquierda
a++/2 <b && (a++/2> b 11 (a* 2<b * 4))=5 /2<b && (a++/2> b 11 (a* 2<b * 4))=2< 3 && (a++
/ 2 > b 11 (a * 2 < b * 4)) = true && (a++/ 2 > b 11 (a* 2 < b * 4))
Tras obtener el valor de la variable a, esta se ha incrementado en 1, valiendo en este momento 6. Como la
parte izquierda del operador && vale true hay que evaluar su parte derecha. Para ello se comienza
evaluando la parte izquierda del operador 11
true && (a++/ 2 > b 11 (a* 2 < b * 4)) = true && (6 / 2 > b 11 (a* 2 < b * 4)) = true && (3 > 3 11 (a* 2 <
b * 4)) =true && (false 11 (a* 2 < b * 4))
Tras obtener el valor de la variable a, esta se incrementa en 1, valiendo en este momento 7. Como la parte
izquierda del operador II vale false hay que evaluar su parte derecha
true && (false 11 (a* 2 < b * 4)) =true && (false 11 (14 < 12)) =true && (false 11 (false)) =true && (false)
= false
Evaluándose, finalmente, la expresión a false.
Comentario: Cuando en una expresión hay expresiones entre paréntesis, en primer lugar se evalúan los
paréntesis más internos.
Ejercicio 1.16:
Dado el siguiente programa, indique qué escribe en pantalla. Justifique su respuesta.
public class OperadoresPrePostincremento {
public static void main(String[J args) {
int a=3. b=6. e:
e= a/ b:
System.out. pri ntl n( "El va lar de e es: " + e):
e= a% b:
System.out.println("El valor de e es: " + e):
a++:
Programación en Java 2
e= ++a+ ++b;
System.out.println("El valor de a es: " + a):
System.out.println("El valor debes: " + b):
System.out.println("El valor de e es: .. + e):
El valor de e es: o
El valor de e es: 3
El valor de a es: 4
El valor de a es: 5
El valor de a es: 6
El valor debes: 7
El valor de e es: 12
El valor de a es: 7
El valor debes: 8
El valor de e es: 15
El primer valor de e vale O pues se realiza la división entera. El segundo valor que se imprime de e es 3 pues
se calcula el resto de la división entera de 3 con 6. La primera vez que se imprime el valor de a vale 4, pues
antes de imprimirlo se incrementa su valor. La segunda vez ocurre lo mismo y vale entonces 5, pues se
incrementa, esta vez en preincremento antes de imprimir su valor.
Los valores que se imprimen a continuación de a y b son, efectivamente 6 y 7 respectivamente pues ambas
se han incrementado en la expresión que hay delante. Sin embargo, el valor que se imprime de e es de 12 pues
se realiza la suma de a ya incrementado (6) y b antes de incrementarse (6), ya que se utiliza el operador de
postincremento, lo que suma 12. Los últimos valores de a, b y e son, respectivamente, 7, 8 y 15, ya que al
imprimir a y b, ya se han incrementado y al guardar el valor en e se hace con los valores ya incrementados, ya
que tanto para a como para b se utiliza el operador de preincremento.
Ejercicio 1.17:
Dado el siguiente programa, indique qué escribe en pantalla. Justifique su respuesta.
public class ExpresionesConincrementos {
public static void main(String[] args) {
boolean expresión:
int a= 7;
expresión= a++< 10 11 a% 3 == 2:
System.out.println("El valor de la expresión es: "+ expresión):
Planteamiento: Al evaluar las expresiones aritmético-lógicas, como ya se ha visto en los Ejercicios 1.14 y
1.15, la dificultad adicional es que hay que llevar cuenta de cómo se realiza el incremento, bien preincremento
o bien postincremento, de la variable a.
En la primera expresión aritmético lógica tanto la parte a la izquierda del operador && como la de su derecha
valen true, ya que en la parte de la derecha al hacerse el incremento en preincremento a valdrá 8 y por tanto
8 % 2 vale, ciertamente, O. En la segunda expresión aritmético lógica el valor de a se incrementa a 9, y este
valor sí es mayor que 6 por lo que la expresión vale true. En la tercera expresión aritmético lógica en la
primera comparación del valor de a, esta variable vale 9 y, por tanto, sí es menor que 10. Cuando pasa a
evaluar a en la siguiente comparación a vale 10, por lo que al hacer 10 % 2, el valor es, efectivamente, O. En
la última comparación también es cierto que 10 <= 10, por lo que la expresión completa vale true.
En la cuarta expresión aritmético lógica en la primera comparación del valor de a, esta variable vale 10 y,
por tanto, es falso que sea menor que 1O. Sin embargo, cuando se evalúa la parte derecha del operador II a ya se
ha incrementado al valor 11, por lo que sí es cierto que 11 % 3 es igual a 2 y, por tanto, la expresión vale true.
Para terminar se imprime el valor de a, que como se puede observar se ha incrementado en cuatro veces,
por lo que su valor final es de 11.
ENUMERADOS
Ejercicio 1.18:
Escriba un programa que defina un enumerado para los días de la semana. En el programa defina una
variable del enumerado y asígnele el valor del día que corresponde al martes. A continuación, escriba por
pantalla dicha variable y escriba el valor del enumerado correspondiente al domingo.
Planteamiento: Los valores del enumerado se escriben, como indica el convenio, todos en mayúsculas. Para
declarar una variable para este tipo de dato se utiliza el nombre dado al enumerado. Para asignarle el valor del
martes hay que poner delante el nombre del enumerado, un punto y el nombre del valor que corresponde al
martes. Para escribir el valor del domingo se pone, de la misma forma, el nombre del enumerado, un punto y
el nombre del valor que corresponde al domingo.
Pmgramaclón en Java 2
Solución:
public class Enumerados
public enum DíasSemana {LUNES. MARTES. MIERCOLES. JUEVES. VIERNES. SABADO. DOMINGO}
Ejercicio 1.19:
Escriba en Java los siguientes tipos enumerados:
Planteamiento: Los valores del enumerado se escriben, como indica el convenio, todos en mayúsculas. Para
declarar los valores de cada uno de los enumerados se utilizarán los nombres que son de aplicación para cada
uno de ellos.
Solución:
a) Los días laborables
enum DíasLaborables {LUNES. MARTES. MIÉRCOLES. JUEVES. VIERNES}
b) Los tres primeros meses del año
enum TresPrimerosMeses {ENERO. FEBRERO. MARZO}
c) Las calificaciones de un alumno
enum Calificaciones {NO_PRESENTADO. SUSPENSO. APROBADO.
NOTABLE. SOBRESALIENTE. MATRÍCULA_DE_HONOR}
d) Los colores primarios
enum ColoresPrimarios {ROJO. AMARILLO. AZUL}
e) Las notas musicales
enum NotasMusicales {DO. RE. MI. FA. SOL. LA. SI}
h) Los colores del arco iris
enum ColoresArcoiris {AMARILLO. ROJO. ANARANJADO. AZUL. VERDE. AÑIL. VIOLETA}
i) Los colores de síntesis de la televisión
enum ColoresTelevisión {ROJO. VERDE. AZUL}
O también en inglés, por ejemplo:
enum RGB {RED. GREEN. BLUE}
Ejercicio 1.20:
Escriba un enumerado para los tipos de lavado de un túnel de lavado que guarde la información de los
tiempos. Los tipos de lavado son básico, normal y super y el tiempo que se tarda en cada uno es de 3, 5 y 8
minutos, respectivamente. Escriba un programa que muestre su funcionamiento.
Introducción a la programación
Planteamiento: Se escribe el enumerado con los valores correspondientes. Hay que declarar un atributo para
el tiempo y un método para obtenerlo. Para probarlo en una clase se declara una variable y se usa para ella el
método que obtiene el tiempo.
Solución:
enum Tipolavado{BASIC0(3), NORMAL(5). SUPER(8);
private int tiempo;
Tipolavado(int tiempo){
this.tiempo = tiempo;
Ejercicio 1.21:
Escriba un programa que solicite al usuario una cantidad en segundos y la convierta a días, horas, minutos
y segundos.
Planteamiento: Tras solicitar el número de segundos, el programa debe dividir sucesivamente el dato entre 60
para obtener los minutos, entre 60 para obtener las horas y entre 24 para obtener los días.
Solución:
import java.util.*;
Ejercicio 1.22:
Escriba un programa que solicite al usuario el tamaño del lado de un triángulo equilátero y calcule su
perímetro y su área.
Planteamiento: Tras solicitar el tamaño del lado, que ha de ser un número real, pues es una medida que
seguramente no sea un número de metros o de centímetros exactos, se calcula el perímetro como tres veces el
lado. Para calcular el área se necesita la base, que es un lado, y la altura, que se obtiene utilizando el teorema
de Pitágoras entre un lado y la mitad de la base.
Solución:
import java.util .Scanner;
perímetro= 3 * lado;
double altura= Math.sqrt(lado * lado - (lado/2.0) * (lado/2.0));
área= lado* altura/ 2:
Ejercicio 1.23:
Escriba un programa para calcular el consumo medio de un automóvil. Para ello el programa debe solicitar
información sobre las tres últimas veces que se repostó combustible. De la primera solicitará el precio del
litro del combustible, el total pagado en llenar el depósito y el número de kilómetros que marcaba el cuenta-
kilómetros. De la segunda vez sólo solicitará el precio del litro del combustible y el total pagado en llenar el
Introducción a la programación
dep6sito, y de la tercera vez, solicitará el valor que indicaba el cuentakil6metros. Con estos datos debe
calcular el consumo por cada 100 km y el coste por kil6metro.
Planteamiento : Para calcular el consumo medio hay que tener en cuenta cuántos kilómetros se han hecho
con el automóvil y cuántos litros de combustible se han consumido. El total de litros de combustible
consumidos es la suma de litros de los dos repostajes realizados, ya que de lo que se reposte en el último
no se puede conocer cuántos kilómetros se van a hacer hasta que se consuma el combustible que se ha
echado. A partir del precio por litro y el total pagado se puede obtener el número de litros que se han
echado en el depósito. Se hará la suma de los litros según se vayan introduciendo los datos. El consumo
por cada 100 km se calcula como el consumo total dividido por el número de kilómetros multiplicado por
100. El coste por kilómetro se calcula como lo que se ha pagado en los repostajes dividido por el total de
kilómetros realizados.
Solución:
import java.util.*:
System.out.príntln():
System. out. print( "Introduzca el precio por 1itro del segundo repostaje: "):
preciolitro = teclado.nextDouble():
System.out.print("Introduzca el coste total del segundo repostaje: "):
pagado= teclado.nextDouble():
litros+= pagado/preciolitro:
coste+= pagado;
System.out.println():
System.out.print("Introduzca el valor del cuentakilómetros en el tercer repostaje: ");
kmFinal = teclado.nextlnt():
kilómetros= kmFinal - kminicial:
Aviso: Al utilizar la clase Scanner para leer los datos, éstos se leen localizados. Esto significa que para
introducir un número real, por ejemplo el coste por litro, hay que escribirlo con coma decimal, no con punto
decimal. Si se hace con punto decimal dará un error al intentar convertirlo a un número válido. Además, si en
un momento que se esperaba un número entero, se introduce otro tipo de dato, el sistema termina abruptamente.
Ejercicio 1.24:
Escriba un programa que calcule cuánto le dará su banco después de realizar una imposición a plazo fijo.
Para ello el programa debe pedir la cantidad que desea invertir en el banco, el tipo de interés anual que le
paga el banco por el dinero y el plazo que se mantiene la inversión. El programa debe calcular el dinero que
se obtiene después de dicho plazo. Recuerde que al pagarle los intereses el banco le retendrá el 18% para
hacienda. Escriba los mensajes apropiados para que el usuario pueda seguir el proceso de cálculo realizado.
Planteamiento: Hay que realizar un programa que utilice variables donde se vayan recogiendo los valores que se
piden al usuario, que serán el capital a invertir (capital Invertido), el tipo de interés anual (interésAnual) y los
meses que se mantiene la inversión (meses Inversión). El dato de la retención que se aplica sobre los intereses es fija
del 18%, por lo que se definirá como una constante (RETENCION). Se declarará un objeto de la clase Scanner para
solicitar al usuario los valores y leerlos. Después se realizarán los cálculos y se imprimirán por pantalla los resultados.
Solución:
import java.util.*;
public class CalculointeresesUsuario
public static void main(String[J args)
final double RETENCI0N = 18:
final int MESES_AÑO = 12;
Scanner teclado= new Scanner(System.in);
System.out.print("Introduzca la cantidad que desea invertir: "):
double capitallnvertido = teclado.nextDouble();
System.out.print("Introduzca el interés anual que le ofrece el banco: ");
double interésAnual = teclado.nextDouble():
System.out.print("Introduzca el número de meses de la inversión: "):
int mesesinversión = teclado.nextint();
System.out.println();
System.out.println("Cálculo de intereses."):
System.out.printf("Dinero a invertir: %.2f€. \n". capital Invertido):
System. out. printf(" Interés anual: %. 2f%%. \n". interésAnual):
System. out. pri ntf(" Intereses a los %d meses: %. 2f€. \n".
mesesinversión. interesesübtenidos):
System.out. printf( "Retención que se real iza: %. 2f€. \n". retención):
System .out. pri ntf(" Intereses a cobrar: %. 2f€. \n". i nteresesCobrados):
Aviso: Recuerde que al utilizar la clase Scanner los datos se leen localizados, por lo que se debe introducir los
valores no enteros con coma decimal.
Clases y objetos
/**
* Estructura de una clase en Java
*/
public class NombreDeClase {
// Declaración de los atributos de la clase
En el caso de ser una clase distinta de la clase principal, el método ma i n( ) no suele aparecer. Una clase es la
descripción (modelo) de un tipo de objetos. Una aplicación, un programa, se compone de un conjunto de clases, que
crean objetos que interactúan entre sí. El nombre de la clase se empezará, como convenio de programación, en
mayúscula. Una vez que la clase está disponible, el programador puede instanciar, crear, objetos de dicha clase. Por
ello, los términos "objeto" e "instancia de clase" o, simplemente, "instancia" se usan como sinónimos.
Para disponer de un objeto de la clase hace falta declarar una variable y crear el objeto. Suponga que dispone de
una clase Al umno de la siguiente forma, donde se ha suprimido su contenido:
class Alumno { }
Alumno al umnol;
Al umno a1umno2;
Referencia null
Una referencia a un objeto puede no tener asignada ninguna instancia. Existe un valor especial, llamado nu11, que indica
cuándo una referencia no tiene asignada ninguna instancia. Como ejemplo, se declara un nuevo al urnno3 de la clase Alumno:
Cuando una referencia a un objeto vale nul l, no se puede utilizar como objeto, pues no existe como tal.
en este momento, las variables alumnol y alumno2 hacen referencia al mismo objeto de la clase alumno. Ello implica
que cualquier modificación del objeto alumno 1 modifica también el objeto al que hace referencia alumno2, ya que
realmente es el mismo.
2.2 ATRIBUTOS
Los atributos permiten guardar la información de un objeto. Por ejemplo, para un alumno se necesita saber la siguien-
te información: el nombre, los apellidos, el curso en que está matriculado, si su horario es de mañana o de tarde, etc.
Estos datos se almacenan en campos o atributos que se declaran como variables en el ámbito de la clase. La declara-
ción de atributos se hace de la siguiente forma:
el ass Al umno
String nombre:
String apellidos:
int añoDeNacimiento:
int númeroPersonal; // Número Personal: identificativo único
String grupo:
Horario horario= Horario.MAÑANA;
En este ejemplo, se ha declarado que la clase Alumno contiene seis atributos, nombre, ape 11 idos, añoDeNacimi ento,
númeroPersonal, grupo y horario. El Horario se ha definido como un enumerado con dos posibles tumos, MAÑANA y
Clases y objetos
TARDE. Como puede observar se puede dar un valor inicial a los atributos en la declaración. De esta forma se ha
indicado que el horario predeterminado para un alumno es el de mañana.
Si los atributos no se declaran como privados ni protegidos (consulte el Capítulo 3), se puede acceder a sus valores
con la notación objeto. atributo. Por ejemplo, para imprimir por pantalla el nombre del a1umnol, se puede escribir:
Aunque es posible acceder a un atributo de la forma indicada, suele ser preferible acceder a los mismos mediante
un método, llamado en este caso método de acceso.
2.3 MÉTODOS
Los métodos sirven para definir el comportamiento del objeto en sus interacciones con otros objetos. Siguiendo el
ejemplo de objetos de la clase Al umno se puede pedir su nombre, asignarle grupo, etc.
class Alumno {
String nombre;
String apellidos;
int añoDeNacimiento;
int númeroPersonal; // Número Personal: identificativo único
String grupo;
Horario horario~ Horario.MAÑANA;
Se han añadido dos métodos a la clase Alumno, uno llamado dameGrupo() para pedir a un objeto de la clase Alumno
el grupo al que asiste a clase y otro ponGrupo () para poder asignar un nuevo grupo a un Alumno. Se ha omitido por
claridad el cuerpo con el código de los métodos.
Para utilizar un método de la clase se utiliza la notación objeto.metodo( ), pasando entre los paréntesis los argu-
mentos que necesite el método al que se llama. Por ejemplo, para dar al al umnol el grupo "INF-01" y luego imprimir
por pantalla el grupo que tiene asignado, solicitándoselo mediante su método dameGrupo( ), se puede escribir:
Además de utilizar los nombres ponXXX() para los métodos que asignan un valor a un atributo y dameXXXX()
para los métodos que devuelven el valor del atributo, suele ser común utilizar la forma inglesa setXXXX() y getXXXX(),
respectivamente. En los ejemplos de los distintos capítulos, se usará una u otra indistintamente, prefiriéndose la
versión inglesa en los capítulos avanzados.
Valor de retorno
Los métodos pueden realizar una función y no devolver un valor, lo que se indica con la cláusula void, o pueden
comportarse como una función y devolver un valor primitivo o una referencia a un objeto. En este caso, se pone
Programación en Java 2
delante del nombre del método el tipo o clase del valor devuelto. En el caso del método dameGrupo(), el método
devuelve una referencia a un objeto de la clase Stri ng. Para devolver un valor dentro del método, se utiliza la
sentencia return. El método dameGrupo() se puede escribir:
Autoreferencia thi s
Para referirse a los atributos del objeto desde un método del mismo, se puede hacer directamente con su nombre o
utilizando thi s. Esta palabra del lenguaje se utiliza, sobre todo, cuando existe ambigüedad entre nombres de parámetros
de un método y atributos del objeto (otros usos se explican más adelante). Por ejemplo, en el siguiente método
thi s funciona como una referencia especial, de forma que thi s. grupo se refiere al atributo grupo declarado en la
clase, para diferenciarlo de la variable grupo declarado como parámetro del método.
Sobrecarga
La única limitación en la elección del nombre de un método es que, en una clase, todos los métodos deben tener
diferente signatura (básicamente distinto nombre y parámetros). Esto permite que existan varios métodos con el
mismo nombre pero con diferentes parámetros. Por ejemplo, se podrían tener dos métodos de nombre ponGrupo( ).
Dependiendo de los valores de los argumentos con que se llame al método ponGrupo , se ejecutaría uno u otro de los
definidos.
2.4 CONSTRUCTORES
Al principio del capítulo se ha visto que para crear un objeto se usa la instrucción new seguida del nombre de la clase
y una pareja abre paréntesis - cierra paréntesis:
Esta operación invoca al constructor por defecto, que se proporciona automáticamente y tiene el mismo nombre
que la clase.
da fonna. Para
Lo habitual es que al escribir una clase se desee construir los objetos de la clase de una determina
acceso, el nombre de la clase,
se escribe uno o más constructores. Para definir un constructor, se pone el tipo de
de código, de la fonna:
parámetros que acepta, si lanza excepciones (opcional) y un cuerpo o bloque
class Alumno {
Alumno(String nombre. String apellidos. int año) {
this.nombre ·= nombre:
this.apellidos = apellidos:
this.añoDeNacimiento = año:
r por defecto ya no
Los constructores declarados sustituyen al proporcionado por defecto. Por tanto, el constructo
nar los valores apropiado s de acuerdo
se puede utilizar. Ahora, para construir cualquier alumno es necesario proporcio
con el constructor que se utilice:
class Alumno {
Alumno(String nombre, String apellidos. int año) throws Exception
// Si el nombre o los apellidos son cadenas null
// se lanza una excepción y el objeto no se crea
if (nombre== null 11 apellido s= null)
throw new Exception("Argumentos no válidos");
// Si el año es negativo
Programación en Java 2
this.nombre= nombre;
this.apellidos= apellidos:
thi s. añoDeNaci miento= año·:
Autoreferencia thi s
En la construcción de objetos se puede utilizar un constructor ya definido desde otro constructor. Para ello
se utiliza
la referencia thi s () seguida de los parámetros del constructor que se desea invocar. Esta llamada sólo
se puede
realizar como primera sentencia de un método. De esta forma, los constructores de la clase se pueden escribir:
class Alumno {
Alumno(String nombre. String apellidos. int año) throws Exception {
// Si el nombre o los apellidos son cadenas null
// se lanza una excepción y el objeto no se crea
if (nombre== null 11 apellidos== null)
throw new Except ion ( "Argumentos no vá l idos" ) ;
// Si el año es negativo
// se lanza una excepción y el objeto no se crea
if (año< O)
throw new Exception("Año incorrecto");
this.nombre= nombre:
this.apellidos= apellidos:
this.añoDeNacimiento= año:
if (grupo== null)
throw new Exception("Grupo no especificado"):
this.grupo= grupo:
this.horario= horario:
ATRIBUTOS
!Ejercicio 2.1:
Definir una clase que represente a un coche. En la definición se debe incluir:
" el modelo,
• el color,
• si la pintura es metalizada o no,
" la matrícula,
" el tipo de coche, que puede ser MINI, UTIUTARIO, FAMIUAR o DEPORTNO
• el año de fabricación
" la modalidad del seguro, que puede ser a terceros o a todo riesgo
Planteamiento: Al diseñar una clase, hay que prestar especial atención a los atributos que se incluyen y sus
tipos. Para los atributos hay que elegir nombres significativos, por ejemplo, "modelo" es un buen nombre para
el atributo que representa el modelo del coche. Al elegir el tipo de un atributo, se debe pensar tanto en los
valores que puede tomar, como en las operaciones que se van a aplicar.
Para el modelo, el color y la matrícula, se elige el tipo Stri ng. Para determinar condiciones que se satisfa-
cen o no, se debe elegir un boo lean, como es el caso de si la pintura es metalizada o no.
Cuando un atributo puede tomar una serie de valores, lo más adecuado es utilizar un tipo enumerado,
eligiendo los nombres adecuados para los diferentes valores. De esta forma, para el tipo de coche se usa un
enumerado con los valores que sugiere el enunciado.
Para el año de fabricación, se usa un número entero. Evidentemente, valores negativos o muy grandes
podrían no ser legales, pero queda a cargo del programador comprobarlo.
Por último, para la modalidad de seguro, de nuevo es adecuado un enumerado, con los valores { A_TERCEROS,
A_TODO_RIESGO }.
Solución:
enum TipoDeCoche { MINI, UTILITARIO, FAMILIAR. DEPORTIVO}:
String modelo:
String color: Los nombres de los atributos han de
boolean esMetalizado: «t~---~1 ser lo más significativos posible, pero
String matricula; no han de ser demasiado largos.
TipoDeCoche tipo:
int añoDeFabricación:
TipoDeSeguro seguro; 4~----1 Escoger adecuadamente los tipos de
los atributos no siempre es tarea fácil.
Comentario: Se podría pensar en utilizar un valor de tipo boo lean para la modalidad de seguro, por ejemplo,
boolean seguroATerceros. Se usaría el valor true cuando se disponga de un seguro a terceros, y false cuando
el seguro sea a todo riesgo. En general, no es una buena decisión usar los booleanos para atributos que toman
Programación en Java 2
dos valores. Por un lado, no queda claro el significado del valor false. Por otro, se pueden aplicar operaciones
que quizá no tengan sentido. Lo peor es que compromete la extensibilidad del programa: si se necesitara otra
modalidad de seguro habrá que modificar muchas líneas de código, mientras que añadir un valor nuevo a un
enumerado es sumamente sencillo.
Aviso: En este problema se ha abordado la elección de los atributos y sus tipos, sin tener en cuenta el tipo de
acceso de los mismos; esto se tratará en posteriores ejercicios.
Ejercicio 2.2:
Se desea imprimir el modelo y el color de un coche dado. Para ello, se pide escribir un método, que acepte un
objeto de la clase Coche. Si dicha referencia no es null, el método deberá imprimir el modelo y el color. Si es
null, el método no hará nada.
Planteamiento: No se dice el nombre del método, por lo que se elige uno significativo del problema, por
ejemplo, i mpri meCoche. Este método acepta una referencia de la clase Coche. Se usa una sentencia i f para
comprobar si la referencia es nu l l o contiene un objeto, en cuyo caso se imprime el modelo y el color.
Valor de retorno: El método no necesita devolver ningún valor de retomo por lo que se utiliza la cláusula voi d.
Solución:
public void imprimeCoche (Coche coche) {
Comentario: En el ejercicio siguiente se verá una forma más conveniente de escribir métodos que añaden
comportamiento a una clase.
Aviso: Es un error común que en ejecución se use un método o atributo de una referencia que está a nul l. Esto
provoca un error en tiempo de ejecución (RunTi meError) denominado Nul l Poi nterExcept ion, que normalmen-
te terminará la ejecución del programa. Es una buena práctica asegurarse de que al usar una referencia, no
contendrá el valor especial nu 11.
MÉTODOS
Ejercicio 2.3:
Añadir a la clase Coche del Ejercicio 2.1 un método de nombre imprimeCoche que imprima el modelo y el
color del coche.
Planteamiento: Cuando se invoca un método de un objeto, desde el mismo se puede acceder directamente a los
atributos de la clase. Por tanto, simplemente se han de imprimir los atributos modelo y color.
Parámetros: Ninguno. Al ser un método de la clase Coche, no necesita ningún valor como parámetro ya que se
dispone del modelo y color del coche como atributos.
Valor de retorno: El método no necesita devolver ningún valor de retomo por lo que se utiliza la cláusula voi d.
ses y objetos
Solución:
enum TipoDeCoche { MINI. UTILITARIO. FAMILIAR. DEPORTIVO};
class Coche {
String modelo;
String color:
boolean esMetalizado:
String matricula;
El comportamiento de la clase
Ti poDeCoche tipo: "'l~,-------- --------11 Coche se recoge en su definición.
int añoDeFabricación:
TipoDeSeguro seguro:
Comentario: Este ejercicio es similar al anterior en cuanto a funcionalidad. Sin embargo, el comportamiento
de los objetos ha de recogerse siempre en la definición de la clase y no depender de funciones externas en la
medida de lo posible.
Ejercicio 2.4:
Escribir un programa que tenga una instancia de mi coche, que es un Rolls Royce de color dorado. El
programa ha de imprimir un mensaje que diga de qué modelo y color es mi coche.
Planteamiento: Los objetos han de usarse por medio de referencias. Por tanto, habrá que declarar una referen-
cia a la clase Coche. Además, hay que elegir un nombre significativo para la referencia. Como en este caso, se
guarda la información de mi coche, el nombre mi Coche (u otro similar) puede ser adecuado. Luego se inicializan
los atributos modelo y color. Para ello, se escribe el nombre de la referencia, un punto, y el nombre del atributo,
de la forma mi Coche.modelo. Y con el operador de asignación ("=") se le asigna el valor "Ro 11 s Royce". Lo
mismo aplica al atributo color. Por último, se imprimen esos valores; como la clase Coche ya dispone del
método imprimeCoche() (del ejercicio anterior), se puede invocar dicho método de la forma
miCoche.imprimeCoche().
Solución:
enum TipoDeCoche { MINI, UTILITARIO. FAMILIAR, DEPORTIVO};
class Coche {
String modelo:
String color:
boolean esMetalizado:
String matricula;
TipoDeCoche tipo;
int añoDeFabricación:
Programación en Java 2
TipoOeSeguro seguro:
class pruebaCoche
public static void main (String args[J)
Coche miCoche= new Coche():
Ejercicio 2.5:
Escriba una clase que represente un Semáforo, que podrá estar rojo, ámbar o verde. La clase tendrá un
atributo llamado color, inicialmente a rojo. También dispondrá de un atributo que determine si el semáforo
está parpadeando. Inicialmente, el semáforo no está parpadeando.
Planteamiento: Para describir el color del semáforo, se usa un tipo enumerado con los tres posibles colores
denominado Col orSemáforo. Después, se escribe la clase Semáforo, que tendrá dos atributos: el primero será el
color, de tipo ColorSemáforo; el segundo representará si el semáforo está parpadeando, para lo que se usa un
boolean.
Solución:
enum ColorSemáforo { ROJO, ÁMBAR, VERDE }: ....~ - - - - - - 1 1 Este enumerado representa el color
que puede tomar un semáforo.
public class Semáforo {
Se pueden inicializar los atributos de
ColorSemáforo color= ColorSernáforo.ROJO: 4
-4 ---~1 un objeto en la misma línea que se
boolean estáParpadeando = false: declaran.
Comentario: Los atributos de los objetos pueden tomar un valor inicial en la misma línea que se decla-
ran. No obstante, lo normal es que cada objeto tenga valores distintos, en cuyo caso se proporcionará
uno o más constructores para el valor inicial de los atributos de un objeto, como se verá en siguientes
ejercicios.
Aviso: Para los atributos que especifican condiciones que se cumplen o no, es muy habitual utilizar el tipo
boo lean. Los nombres de dichos atributos suelen ser adjetivos o, como en el ejemplo, una palabra formada por
el verbo "estar'' y la condición.
s y objetos
Escriba un programa que instancie un semáforo de la clase Semáforo del ejercicio anterior. El programa
escribirá por pantalla el color del semáforo. Luego pondrá el semáforo en ámbar y volverá a imprimir el
color.
Planteamiento: Se define una clase para el método ma in ( ), que se llamará PruebaSemá foro. En dicho método
ma in ( ), se declara un semáforo, llamado s1, por ejemplo. Se instancia mediante new un objeto de la clase
Semáforo y se asigna a sl. Ahora se puede imprimir su color, luego se cambia a ámbar y se vuelve a imprimir.
Solución:
enum ColorSemáforo { ROJO. ÁMBAR. VERDE};
class Semáforo {
class PruebaSemáforo {
Comentario: Hasta que no se genera el objeto con new, la referencia sl contiene el valor nul l (inicialización
por defecto de Java). Es muy común hacer ambas cosas en la misma línea, como se presenta a continuación:
Aviso: La forma utilizada en la solución para acceder a los atributos no se considera la más adecuada. Ya se
verá en otros ejercicios los métodos accesores y los derechos de acceso. En el siguiente capítulo se hará hinca-
pié en el tema.
Ejercicio 2.7:
Escriba un programa que disponga de una clase para representar las asignaturas de una carrera. Una asig-
natura tiene un nombre, un código numérico y el curso en el cual se imparte. Los valores iniciales han de
proporcionarse en el constructor. La, clase ha de tener métodos para obtener los valores de los atributos. El
programa ha de construir un objeto con los siguientes valores: nombre "Matemáticas", código 1017, curso l.
A continuación, el programa ha de imprimir los valores del objeto por pantalla.
Planteamiento: Se proporcionarán dos clases, una que representa a las asignaturas, llamada Asignatura, y
otra para el programa, llamada EjercicioAsignatura. La clase Asignatura dispondrá de un constructor que
acepta los valores para representar una asignatura: el nombre, el código y el curso. El nombre del constructor
Programación en Java 2
es el mismo de la clase, Asignatura en este caso. Los atributos serán privados y se disponen de métodos para
acceder a sus valores. Normalmente, estos métodos denominados accesores, se suelen llamar como el atributo,
anteponiendo el verbo dame o get. En la clase EjercicioAsignatura, habrá un método main( ), en el que se crea
la asignatura de matemáticas de primero y luego una sentencia para imprimir sus datos.
Solución:
class Asignatura {
class EjercicioAsignatura {
Comentario: Se podría haber incluido el método main() en la clase Asignatura, con lo que con una sola clase
se hubiera resuelto el ejercicio. Es muy típico añadir un ma in ( ) a clases intermedias para probar o ejercitar la
clase, aunque dicho método ma i n( ) no forme parte del proyecto en el que participa la clase.
Respecto de los métodos accesores, nótese que no disponen de parámetros, lo que se indica con los parén-
tesis vacíos, como en dameNombre ( ) . Estos métodos devuelven el mismo tipo que el atributo al que acceden.
Aviso: La codificación de los métodos accesores es tremendamente trivial, lo que suscita la tentación de elimi-
narlos y poner los atributos como públicos. Se desaconseja esta práctica, pues el programador ha de responsa-
bilizarse de una clase y no debe permitir que se modifiquen los atributos de forma arbitraria.
'cio 2.8:
Definir una clase que represente un punto en un espacio bidimensional. La clase debe disponer de un cons-
tructor con las coordenadas del punto y métodos accesores a las coordenadas.
Planteamiento: En un espacio bidimensional, un punto se representa por un par ordenado de números reales.
Se deben elegir nombres representativos para los mismos, como x e y. El tipo más adecuado dependerá del tipo
de aplicación en que se usen estos objetos. Como el enunciado no dice nada, se usará doub le. Para asegurar la
consistencia de un objeto, es conveniente que los atributos sean privados y existan métodos públicos para
averiguar su valor. Estos métodos se llamarán dame X() y dameY(), sin parámetros, y con tipo de retomo igual al
del atributo que devuelven.
Solución:
public class Punto
Los atributos son privados, de forma
prívate double x . y;~ que sólo pueden modificarse
mediante métodos de la clase.
Comentario: Fíjese que se ha elegido doub le como tipo para las coordenadas. No obstante, ciertas aplicacio-
nes (por ejemplo, gráficos) podrían requerir int, o podría ser suficiente float.
Aviso: Se ha elegido representar el punto en coordenadas cartesianas. Se podría representar en polares, lo que
supondría tener que programar las conversiones entre los diferentes sistemas de representación.
Ejercicio 2.9:
Escriba un programa que instancie cuatro puntos: el primero situado en el origen, el segundo situado en
(5, 3), el tercero en (2, -1) y para el cuarto como punto medio entre el segundo y el tercero.
Planteamiento: Los tres primeros puntos se crean con los valores literales que nos proporciona el enunciado.
Para el último, se calculan sus coordenadas como las medias entre las respectivas coordenadas del segundo y
tercer puntos.
Solución:
public static void main (String args[J) {
Punto pl = new Punto (O. O): // origen de coordenadas
Comentario: Los tres primeros puntos se crean con los valores literales que nos indica el enunciado. Para el
cuarto punto, se usan los métodos accesores de los puntos, obteniendo las coordenadas de los puntos segundo
y tercero, haciendo luego la semisuma.
Para crear objetos, se usa la instrucción new seguida del nombre de la clase y después, entre paréntesis, los
parámetros para el constructor de la clase.
Ejercicio 2.10:
Añada a la clase Punto un constructor sin parámetros que permita construir puntos en el origen de coordenadas.
Planteamiento: Se pide que los valores de las coordenadas sean (0, 0). Se pueden inicializar directamente,
pero es más conveniente invocar al otro constructor con los argumentos a O. De esta forma, se dispone de un
solo constructor que realiza el código de inicialización. Para invocar a otro constructor, se utiliza el nombre
especial thi s, seguido de los parámetros que espera ese constructor. En este caso, se escribe thi s (O.O). Esta
invocación ha de aparecer como la primera sentencia del cuerpo del constructor.
Solución:
// sólo se incluye el constructor. el resto del código como
// el ejercicio anterior
public Punto() {
thi 5 ( o. o) ; - . . A - - - - i i Se invoca al constructor anterior con
los valores deseados.
Comentario: Es muy adecuado tener diferentes constructores cuando se desea que el objeto tenga valores
iniciales tomados de diferente forma.
Aviso: Cuando los diferentes constructores tienen código común, es conveniente que unos se llamen a otros, si
es posible, en lugar de repetir código.
Ejercicio 2.11:
Añada un método a la clase Punto que calcule la distancia a otro punto.
Planteamiento: El método debe recibir como parámetro el punto al cual se calcula la distancia. Se aplica la
fórmula de la distancia euclídea entre dos puntos con ayuda de la clase Math. En dos variables auxiliares se
almacenan las diferencias entre las coordenadas de los puntos.
Solución:
// sólo el método distancia
public double distancia (Punto p)
double diffX = x - p.x;
double diffY = y - p.y;
return Math.sqrt (diffX * diffX + diffY * diffY); 4(---1[ d = ✓ (a. -b.}2 +(ay -by}2
l
s y objetos
Comentario: Para elevar un número al cuadrado, se podría haber optado por la función pow, escribiendo
alternativamente:
Aviso: El método distancia puede fallar si se le pasa un punto a nul l. En efecto, si p es nul 1, no se puede
acceder a los atributos.
Modificar el método distancia del ejercicio anterior para que lance una excepción si el punto que se le pasa
es nu 11. La, excepción deberá contener un mensaje descriptivo del problema.
Planteamiento: Se debe modificar la cabecera del método distancia para declarar que ahora va a lanzar
excepciones. Para ello, después de los parámetros se añade la palabra reservada throws seguida del tipo de
excepción que se va a lanzar. En este caso, se usa Exception. Con un if se comprueba si la referencia p
contiene el valor nu 11, en cuyo caso se lanza una excepción. En caso contrario, p contiene un objeto y puede
accederse a sus atributos.
Solución:
!! sólo el método distancia
public double distancia (Punto p) throws Exception {
if(p == null) + - - - - - - - - - - - - - - - - t i El método distancia comprueba
que su(s) argumento(s) son correctos.
throw new Exception("p no puede valer null"):
Comentario: Es muy recomendable que los métodos comprueben primero los valores que se les pasan y, si no
están en un rango aceptable, se lance una excepción, indicando la naturaleza del problema. A la larga, esto facilita
tanto el descubrimiento y diagnosis de errores en programas grandes, como el mantenimiento del programa.
. Ejercicio 2.13:
Escriba un programa que cree un punto en (4, 3) e imprima la distancia del punto al origen de coordenadas.
Planteamiento: Para calcular la distancia de un punto al origen, se aplica el teorema de Pitágoras, resultando
,J
d = x 2 - y 2 • No obstante, dado que se dispone del método distancia a otro punto, se puede calcular la distan-
cia al punto origen de coordenadas.
Solución:
public class distanciaAlOrigen
!/ origen de coordenadas
Punto origen= new Punto (O. O): Se utiliza el método distancia a otro
- punto para hacer el cálculo~
Aviso: Es conveniente estudiar el API de Java y las bibliotecas disponibles para evitar escribir varias veces el
mismo código.
Ejercicio 2.14:
Escriba un método llamado sumaTotal que, dada una lista arbitraria de números enteros, devuelva la suma
de todos ellos. Además, escriba un programa que pruebe dicho método, calculando la suma de las secuencias
{3, 5, 2, 4, 6), la secuencia {2, 10, -1, 2), la secuencia {JO} y la secuencia{}. El programa imprimirá el valor
de dichas sumas.
Planteamiento: El método suma Total deberá aceptar un número variable de parámetros, lo que se indica con
la notación " ... ". Entonces, deberá ir recorriendo todos los parámetros e ir acumulando la suma de cada uno de
ellos. Para ello, se guarda en una variable llamada suma el resultado parcial.
El valor inicial de la variable suma será O. Para sumar los valores que se reciben como parámetro, se usa un
bucle for sobre la lista de valores recibidos en el método. Por último, el método devolverá el valor almacenado
en suma.
Valor de retorno: El valor de la suma acumulada. Como la suma de enteros es un entero, el valor de retomo
será del tipo i nt.
Solución:
public class suma
La notación ... significa que se espera un
public static int sumaTotal (int ... números) {~, - - - - ~ 1 número arbitrario (O o más) de parámetros.
1
int suma= O;
Con un bucle far se recorren los
for Cint num: números) {• ~-------------1 1 p:~rárnet1·os1~onlosque1sellanna~tl miét0<fo. 11
suma+= num;
return suma:
x = sumaTotal (10):
System.out.println("Tercera suma = " + x):
x = sumaTotal ();
System.out.println("Cuarta suma="+ x):
Primera suma= 20
Segunda suma= 13
Tercera suma= 10
Cuarta suma= O
Hay que resaltar la cuarta suma: cuando se llama al método s urna Total , se pasa una lista (array, véase Capítulo 6)
vacía, con O elementos. El cuerpo del bucle for, por tanto, no se llega a ejecutar ninguna vez, con lo que la
variable suma no se modifica.
Aviso: Hay que tener especial cuidado con los métodos con un número variable de argumentos cuando la lista
está vacía. Por otro lado, si se desea disponer de un número variable de argumentos, la variable para ellos debe
ser la última de los parámetros que acepta el método.
Escriba un método de nombre mediaAritmetica que, dada una lista de números reales, calcule y devuelva su
media aritmética. Escriba también un programa que, utilizando dicho método, determine la media de los
números -JO, 5, O, 7, 20. "
Por tanto, hay que calcular la suma de todos los números, de forma similar al ejercicio anterior: para ello se
recorre la lista de los números y se determina su suma. Posteriormente, se divide entre el número de valores en
la lista, información que se puede obtener del atributo l ength de la secuencia.
Valor de retorno: La media aritmética de valores doub le será un valor del tipo doub le.
Solución:
public class mediaAritmetica
[]) {
public stat ic void main (String args
double media:
7. 20):
media= mediaAritmetica (-10. 5. O.
media es = " +media):
System.out.println("La
Solución:
class Trayectoria {
to ... puntos) {
public stat ic double recorrido (Pun
double dist = O.O:
Como primer punto se pone el que
Punto anterior = puntos [ oJ : <11Á_ _ _ _ _ _ _11
está en la posición O.
Comentario: Hay varios puntos que resaltar en este ejercicio; nótese en primer lugar el uso de recon-:tQO
primer caso: el punto pl se pasa dos veces, como origen y final de la trayectoria. Por otro lado, a1 eieé~tafJi!Ste
programa, se imprime lo siguiente:
Se ha recorrido 14.94427190999916
Se ha recorrido O.O
Exception in thread "main" java. lang.ArrayindexOutüfBoundsException: O
at Trayectoria.recorrido(Trayectoria.java:7)
at Trayectoria.main(Trayectoria.java:30)
La primera línea corresponde al recorrido entre los puntos. La segunda, corresponde a la llamada.a recorrí do
con un solo punto. Es conveniente considerar si es correcto que al "recorrer" un solo punto se devuelva un
cero, pues con un solo punto no ha habido trayectoria real. La tercera línea es inaceptable en la mayoría de los
casos: se lanza una excepción (ArrayindexOutüfBoundsException) por intentar acceder a1 primer elemento de
la secuencia en la inicialización de (Punto anterior = puntos[O];) cuando en realidad no hay ningún punto.
Se podría haber protegido el método comprobando el número de parámetros pasados (puntos.si ze),. como en
el siguiente código:
class Trayectoria {
return dist;
Se ha recorrido 14.94427190999916
Se ha recorrido O.O
Exception in thread "main" java.lang.Exception: No hay trayec toria
at Trayectoria.recorrido2(Trayectoria.java:21)
at Trayectoria.main(Trayectoria.java:46)
dist += actual.distancia(anterior):
anterio r= actual;
Clases y objetos
Por otra parte, aunque se ha puesto en el método ma i n( ) que este delega Exception, esto nunca debería ocurrir,
sólo se pone para simplificar el ejercicio, ya que no se tratan excepciones con todo detalle. Sobre el tratamiento
de excepciones de forma apropiada consulte el Capítulo 4.
Ejercicio 2.17:
Escriba la clase Punto con dos métodos llamados distancia. Uno de ellos calcula la distancia a otro punto y
el otro calcula la distancia al origen.
Planteamiento: La clase Punto, como en ejercicios anteriores, tendrá dos atributos para las coordenadas x e y.
Para los métodos distancia, se proporciona uno que admite como parámetro un Punto y devuelve un doub le
con la distancia a dicho punto; asimismo, se escribirá otro método también llamado distancia, pero sin
parámetros, que calcule la distancia al origen.
Parámetros: Uno de los métodos distancia aceptará una referencia a la clase Punto y el otro no dispone de
parámetros.
Valor de retorno: Como la distancia entre dos puntos será un número real, ambos métodos devolverán un
valor del tipo doub le.
Solución:
import java.lang.Math:
prívate double x. y;
Comentario: Cuando se encuentran varios métodos con el mismo nombre, pero que aceptan diferentes
parámetros, bien por diferente cantidad de parámetros o bien por tener los parámetros diferente tipo, se dice
que el método está sobrecargado. Para la sobrecarga no se tienen en cuenta ni las diferencias de acceso, ni el
tipo devuelto ni las excepciones lanzadas. La sobrecarga de métodos es útil cuando se desean hacer cosas
similares con diferentes parámetros.
Aviso: Usar la sobrecarga en exceso dificulta la legibilidad del programa y puede comprometer, por tanto, su
mantenimiento.
Ejercicio 2.18:
Escriba una clase que represente un reloj que señale la hora, el minuto y el segundo. La clase dispondrá de
dos constructores, uno sin parámetros que pone el reloj a 0:0:0 y otro al que se le pasa la hora, los minutos
y los segundos.
Se proporcionarán los siguientes métodos:
" Uno que da la hora, los minutos y los segundos, separados por el carácter ": ", en una cadena.
" Otro que también da la hora pero en formato 24 horas (como el anterior) o en formato 12, en cuyo caso
debe distinguir entre "am" (para las horas de Oa 11) o "pm" (para las horas de 12 a 23 ), también en una
cadena.
.. Un método para poner el reloj en hora. Se le pasa la hora y los minutos, poniendo los segundos a O.
., Un método para poner el reloj en hora al que, además, se le pasan los segundos.
Planteamiento: Existen muchos problemas en los que la representación de la información admite diversos
formatos (por ejemplo, coordenadas polares o cartesianas en el ejercicio de la clase Punto). En general, lo más
adecuado es trabajar en un formato interno, que sea cómodo y fácil de programar y sólo las funciones que
toman datos o los devuelven se preocupan del formato. En este caso, hay que elegir entre representar un reloj
con las horas de O a 23 o bien de Oa 12 y seleccionar "am" o "pm". El formato de O a 23 es más cómodo, pues
no hay que guardar otro atributo con el uso horario.
Los atributos serán, por tanto, tres enteros, para la hora, los minutos y los segundos. No obstante habrá que
comprobar que los valores son correctos, tanto en el constructor como en los métodos que ponen la hora. Si son
incorrectos, se lanza una excepción descriptiva del problema. Como hay que hacer la comprobación en varios
sitios, es conveniente escribir un método que lo haga. A este método se le llamará compruebaHora.
Existirán dos métodos que dan la hora, que se llamarán dameHora( ); el primero, sin parámetros, la devol-
verá como un objeto Stri ng. El segundo necesita un parámetro para determinar el formato de la hora. Para
ello, se proporciona un enumerado con los dos posibles formatos, el de 24 horas y el de 12. En el caso de que
el formato sea de 12 horas y la hora sea de tarde (entre 12 y 23) habrá que restar 12 al valor de la hora y añadir
la cadena "pm". En el mismo formato, pero con la hora entre O y 11 habrá que poner "am".
Por último, existen dos métodos para poner la hora, uno que toma dos parámetros, para la hora y los
minutos, y otro que toma tres parámetros, la hora, los minutos y los segundos.
Parámetros: La hora, los minutos y los segundos serán representados en todos los casos con valores del tipo
i nt. No obstante, se comprobarán los rangos adecuados. Se proporciona un enumerado para distinguir los
formatos de 24 horas y el de 12 horas.
Valor de retomo: El valor devuelto por los métodos dameHora () será un objeto de la clase Stri ng con la hora
en el formato adecuado.
Solución:
· Horario { H24 • H12 } ; .,o¡¡-:----11 Enumerado adicional para determinar
enum T1po
el formato de la hora.
class Reloj {
Clases y objetos
public Reloj()
hora= minutos= segundos= O:
this.hora = hora:
this.minutos = minutos:
this.segundos = segundos:
String dameHora()
return hora+":"+ minutos+":"+ segundos;
res += ":" + minutos + ":" + segundo + ( (hora < 12) ? "am" "pm" ) :
return res:
void ponHora (int hora. int minutos. int segundos) throws Exception {
Programación en Java 2
this.hora = hora:
this.minutos = minutos; De nuevo se invoca a
this.segundos = segundos: compruebaHora para determinar si
los valores son correctos. Si no lo
son la hora no se modifica.
}
Comentario: En este enunciado, existen muchos puntos abiertos. Por ejemplo, los nombres de los métodos, el
tipo de representación de la información, etc. Generalmente, el punto más delicado es elegir un buen modelo
de datos, que permita programar de forma cómoda, sencilla y legible.
Respecto del enumerado TipoHorario, los valores que contienen no pueden ser { 24H. 12H }, como podría
parecer natural, puesto que los identificadores de Java no pueden empezar por un dígito. Por ello, se antepone
la hache delante.
Aviso: Nótese que el constructor sin parámetros NO delega en el otro constructor mediante thi s (O. O. O).
Esto es así para evitar lanzar excepciones (o capturarlas como se verá en ejercicios posteriores del Capítulo 4).
En este caso, se justifica el evitar usar el thi s por la sencillez del código que resulta. Hay que tener en cuenta
que no tiene sentido que el constructor sin parámetros se declare que lanza excepciones, pues siempre debe ser
correcto o no existir.
Por otro lado, el método compruebaHora es privado. Aunque los derechos de acceso se tratan en el siguiente
capítulo, baste decir que de esta forma la clase Re l oj contiene los métodos tal como indica el enunciado, pues
compruebaHora no puede invocarse desde fuera de la clase.
Ejercicio 2.19:
Añada al ejercicio anterior un método para poner la hora especificando si es AM o es PM.
Planteamiento: Una vez más se sobrecarga el método ponHora( ), en este caso se le añade un parámetro para
determinar si la hora es AM o PM. En principio, se podría pensar en pasar una Stri ng, con los valores "am" o
"pm". Pero ello implicaría comprobar que no se ponga otra cadena o un null. Es mucho mejor añadir un
enumerado con los valores { AM. PM }, llamado TurnoHorario.
Al añadir el turno horario quiere decir que las horas se pasan en formato de 12 horas. Hay que comprobar,
entonces, que el rango de la hora es de O a 11. Se puede optar por modificar compruebaHora, que comprobaba
la hora en formato 24 horas o bien en añadir una línea de comprobación adicional. La solución mejor depen-
derá del uso posterior que se quiera dar a compruebaHora. En este caso, se añade una línea adicional.
Parámetros: Además de la hora, los minutos y los segundos como i nt, el turno de horario, de tipo TurnoHora ri o.
Valor de retomo: El método no necesita devolver ningún valor de retorno por lo que se utiliza la cláusula voi d.
Solución:
// Sólo se incluye el enumerado con el turno y el nuevo método ponHora
enum TurnoHorario { AM. PM };
void ponHora(int hora. int minutos. int segundos. TurnoHorario t) throws Exception {
if Chora> 11 ){
throw new Exception ("Hora incorrecta en horario de 12 horas");
Clases y objetos
if ( t == TurnoHorario.PM ){
hora += 12; ---------------11 Se pasa a formato
this.hora = hora;
this.minutos = minutos;
this.segundos = segundos;
Comentario: La hora se almacena en formato 24 horas, como se explicó en el ejercicio anterior. ·'Pt-l!lf.~llfü .
hora es PM, se suman 12 horas al valor de hora recibido.
También se podría haber modificado el método compruebaHora (), quedando un código
nuevo comprueba Hora () y ponHora () quedarían de la siguiente forma:
private void compruebaHora (int hora, int minutos. int segundos. TipoHorario t)
throws Exception {
if ( t = TipoHorario.H24){
if (hora< O 11 hora> 23 ){
throw new Exception ("Error en hora formato 24H");
if ( t == TipoHorario.Hl2){+-------
if Chora< O 11 hora> 11 ){
throw new Exception ( "Error en hora formato 12H");
if (minutos< O 11 minutos> 59 ){
throw new Exception ("Error en minutos");
if (segundos< O 11 segundos> 59 ){
throw new Exception ("Error en segundos");
this.hora = hora;
this.minutos = minutos;
this.segundos = segundos;
Programación en Java 2
Aviso: Evidentemente, si se introduce esta segunda codificación en la clase Reloj, habrá que modificar todas
las invocaciones del método compruebaHora, especificándose si el formato de reloj es de 24 horas o 12 horas,
según corresponda.
Ejercicio 2.20:
Se define la serie de Fibonacci como 1, 1, 2, 3, 5, 8, 13, 21, ... donde los dos primeros términos son 1 y cada
término restante es la suma de los dos anteriores. Formalmente, considerando el O como índice del primer
elemento, el término a; se calcula como:
i= o, i =1
i>l
Se pide escribir dos métodos que calculen el término i-ésimo de la serie de Fibonacci, uno de ellos de forma
recursiva y otro deforma iterativa.
Planteamiento: Se llamará fi bR al método recursivo y fi bI al método iterativo. Ambos tomarán como parámetro
el índice del término que se desea calcular. Fíjese que el primer elemento se denota como a0, empezando con el
índice O. También ambos lanzarán una excepción cuando el índice sea negativo (fuera de rango).
Para la versión recursiva, se escribe la función prácticamente como se define formalmente: con un i f se deter-
mina si el índice es Oo 1, en cuyo caso se devuelve 1; en caso contrario, se devuelve la suma computando recursivamente
(esto es, llamando a fibR) el valor de los anteriores términos. Esto se escribe como fibR(i-1) + fibR(i-2).
Para la versión iterativa, hay que idear alguna forma de ir computando los términos hasta llegar al deseado.
Para ello, se almacenarán los valores inmediatamente anteriores en dos variables, llamadas último y penú l ti -
mo. La suma de estos valores se almacenará en otra variable, llamada res. Con un bucle for se calculan los
términos hasta el i-ésimo, de forma que en cada iteración, res se computa como úl timo + penú l timo y luego
se actualizan sus valores. Las tres variables se inicializan a 1 y el bucle no se ejecutará para los dos primeros
términos.
Parámetros: El índice del término a calcular, como un valor del tipo i nt.
Valor de retomo: El cómputo de la función de Fibonacci, como i nt. Podría también devolverse un valor long
si se desea poder calcular mayores valores de la función de Fibonacci.
Solución:
public int fibR(int i) throws Exception {
if(i<O){
throw new Exception ("Índice negativo"):
penúltimo= último:
último = res : 4~ - - - - - - i i Hay que tener cuidado en el orden
de actualización.
return res:
Aviso: Las funciones recursivas tienen una codificación mucho más legible y elegante de
iterativa. Por tanto, la versión recursiva es mucho más fácil de mantener y de depurar que la
obstante, la implementación recursiva consume más recursos y generalmente tarda más en
versión iterativa. Cuál debe elegirse dependerá sobremanera de los requisitos de ejecución
Ejercicio 2.21:
La función de Ackerman se define para valores enteros no negativos n y m como:
Se pide codificar un método que calcule la función de Ackerman y un programa que imprima los valo~s de
Ackerman (0,0), Ackerman(2,2) y Ackerman (6,6).
Valor de retomo: Un entero (i nt) con el valor de la función de Ackerman. Podría también devolvet111eun valor
1ong si se desea poder calcular mayores valores de la función de Ackerman.
Solución:
public class Ackerman
if ( m = O ){
Programación en Java 2
return n + l;
Comentario: La función de Ackerman es una función recursiva no primitiva, esto es, no es posible codificar
un método iterativo que la implemente. El inconveniente que tiene Ackerman es que consume muchos recur-
sos, aunque el valor de la función no sea muy elevado. Como ejercicio, se podría calcular el número de veces
que se llama al método Ackerman. De hecho, la salida de este programa es:
Ackerman(0,0)= 1
Ackerman(2.2)= 7
Ackerman(3.3)= 61
Exception in thread "main" java. lang.StackOverflowError
at Ackerman.Ackerman(Ackerman.java:20)
at Ackerman.Ackerman(Ackerman.java:21)
at Ackerman.Ackerman(Ackerman.java:21)
at Ackerman.Ackerman(Ackerman.java:21)
at Ackerman.Ackerman(Ackerman.java:21)
at Ackerman.Ackerman(Ackerman.java:21)
at Ackerman.Ackerman(Ackerman.java:21)
donde la última línea se repite un número muy grande de veces, que depende de la configuración del sistema,
la cantidad de memoria instalada, etc.
Aviso: Existen algunos mecanismos, como la Programación Dinámica, para tratar algunos de estos problemas,
pero el tratamiento de los mismos y su justificación excede del propósito de este libro. En el caso de la función
de Ackerman, una implementación mediante Programación Dinámica es una solución muy adecuada. De
todas formas, incluso para valores no muy grandes de m y n, el resultado de Ackerman es demasiado grande
para almacenarlo en un entero.
Ejercicio 2.22:
Escriba un programa que permita modelar el movimiento rectilíneo uniforme de un móvil en un plano. El
móvil puede seguir una trayectoria en cualquier recta del plano. Se conoce la posición inicial del móvil, así
como su velocidad lineal. Escriba, asimismo, un programa que ejercite dichas clases, de forma que se instancie
un móvil que se mueve a una velocidad de 2.4 metros/segundo, que parte de la posición (2.1, 5.2) y se mueve
sobre la recta y = 2x + 1. El móvil se irá moviendo en incrementos de tiempo arbitrarios. El programa ha de
determinar las posiciones en las que se encuentra el móvil tras el paso de 3.5, 4, y 6.2 unidades de tiempo
Clases y obje tos
Solución:
class Punto
private double x. y;
Punto(double x. double y)
this.x = x;
this.y = y;
doub le dameX O {
return x:
double dameY() {
return y;
String posición() {
return "(" + x +","+y +")";
class MovUniforme {
prívate double vel;
MovUniforme(double vel)
this.vel = vel;
double recorrido(double t)
return vel * t;
class Recta {
prívate double a. b;
double pendiente(){
return Math.atan(a);
class Móvil
this.trayectoria = trayectoria;
this.mov = mov: 11 a1var1zacalc:ula la nueva posición pasados t segundos.
void avanza(double t)
Punto intermedio= new Punto (posActual.dameX(),4~:.....-----------.
posActual .dameY()): 1
Punto intennedio para actualizar el punto
double dist = mov.recorrido (t): anterior cuando acaben los cálculos.
posAnterior = intermedio:
Punto posActual(){
return posActual:
m.avanza(3.2):
System.out.println("Me encuentro en"+ m.posActualO.posición());"'...;¡_..---..1
Programación en Java 2
m.avanza(4);
ición() );
System.out. println ( "Me encuentro en " + m. posActual ().pos
m.avanza(6.2);
ción()) ;
System.out.println("Me encuentro en"+ m.pos Actual O.posi
Me encuentro en (2.1,5.2)
Me encuentro en (5.534600413439678.12.069200826879353)
Me encuentro en (6.393250516799597,13.78650103359919)
Me encuentro en (12.189138714479054,25.3782774289581)
Primero determina el recorrido lineal en ese
El método avanza calcula la nueva posición pasados t segundos.
oria, calcula los incrementos en x e y. Por
plazo. Luego, según la pendiente de la recta que representa la trayect
actualiza la anterior.
último, calcula la nueva posición actual a partir de la anterior. Y
de atributos para todos los valores que se
Aviso: Otra posibilidad es crear una única clase que tenga un montón
han de almacenar o calcular. Esto, en general, es una mala idea.
ar una posible solución. Luego, para cada
Siempre hay que entender el problema antes de ponerse a codific
que lo modela.
concepto del problema o de la solución, se propone una clase
Ampliación de clases
class Alumno {
JI Cuenta de alumnos matriculados.
JI inicialmente a O
static int numAlumnos = O:
Dado que tanto el atributo numA1umnos como el método imprimeTotal Alumnos existen aunque no haya objetos se
les llamará desde el programa principal de la siguiente forma:
Alumno.imprimeTotalAlumnos();
class Alumno {
static int numAlumnos:
static {
numAlumnos = O:
3. 2 DERECHOS DE ACCESO
El estado de un objeto es el conjunto de los valores de sus atributos. Una modificación arbitraria, intencionada o por
error, de este estado puede dar lugar a inconsistencias o comportamiento s indeseados del objeto. Sería deseable poder
controlar el acceso a los atributos de los objetos.
Java proporciona mecanismos de acceso a los componentes de una clase, de forma que es posible ajustarlo a las
necesidades de los objetos. Para ello, se antepone a la declaración el modificador de acceso que se requiere:
• Acceso privado (prívate): Los elementos privados sólo se pueden usar dentro de la clase que los define, nunca
desde ninguna otra clase.
• Acceso de paquete: No se pone nada. El acceso a estos componentes es libre dentro del paquete en el que se
define la clase.
e Acceso protegido (protected): Los elementos protegidos sólo se pueden usar dentro de la clase que los define,
aquellas clases que la extiendan y cualquier clase en el mismo paquete.
• Acceso público (publ ic): Dicho elemento se puede usar libremente.
Así, para limitar el acceso a los atributos nombre, apellidos y añoDeNacimiento de un objeto alumno se declara-
rían como:
class Alumno {
private String nombre:
private String apellidos:
private int añoDeNacimiento:
Ampliación de clases
compilación, y sólo se
De esta forma, el intento de cambiar cualquier atributo privado dará lugar a un error de
modificar los valores de los atributos desde los propios
podrá acceder a la parte pública de la clase. Sólo se pueden
modificar los atributos a través de un método ponGrupo( ), éste
métodos de la clase. De esta forma, aunque se puedan
caso contrario lanzar una excepción .
puede verificar que la modificación es segura y en
3.3 PAQUETES
nte relacionados entre sí.
Los paquetes son agrupaciones de clases, interfaces y otros paquetes (subpaquetes), normalme
ción de mayor nivel que las clases. Los paquetes permiten unifi-
Los paquetes proporcionan un mecanismo de encapsula
funcional mente. Por ejemplo, el paquete java engloba una serie de
car un conjunto de clases e interfaces relacionados
de la aplicación . Contiene, a su vez, los subpaquetes ut i l o
paquetes con utilidades de soporte al desarrollo y ejecución
o pertenece a un paquete, la primera sentencia debe tener la sintaxis:
l ang. Para indicar que la clase que se está escribiend
package nombrePaquete;
parte del paquete
Todos los elemento s contenido s en el fichero en el que aparece tal declaraci ón formarán
nombrePaquete.
3.3.1 Uso
se añade una declaración de
Cuando en una clase se quieren utilizar componentes que están en otro paquete diferente,
importación, que puede tener las siguientes formas:
3.3.2 Nombres
n que contiene. El nombre
El nombre del paquete, como todos los identificadores, debe ser representativo de la agrupació
se puede recomend ar incluir el dominio de la empresa para que
puede contener la declaración de subpaquete. Incluso
que pudieran existir o comprars e a otros proveedores.
quede identificado de forma única respecto a otros paquetes
package com.empresa.Matricula:
que contenga dos
Los derechos de paquete no se modifican porque estén contenidos en otro paquete. Un paquete
agrupar paquetes es convenien te p~a el posterior
subpaquetes no implica permisos de acceso entre ellos. Es decir,
desarrollo de código, pero no para modificar los derechos de acceso.
Programación en Java 2
class Direccion{
String calle:
int numero:
Con las clases internas se introduce una nueva sintaxis en el nombrado de las clases, en el operador new, de
creación de una instancia y en la autorreferencia thi s. Como se puede ver en el ejemplo, si se quiere utilizar directa,.
mente la clase interna, por ejemplo, para crear un nuevo objeto, hay que hacerlo NombreCl aseContenedora.
NombreCl ase Interna. Si la clase interna no se ha declarado privada se puede crear un objeto de esa clase interna
mediante referenci aübjetoCl aseContenedora. new NombreCl ase Interna ().
Si dentro de la clase interna se desea hacer una referencia al objeto actual de la clase contenedora se hace mediante
NombreClaseContenedora.this.
Java también permite crear clases locales. Las clases locales son aquellas que se definen dentro de un método y
que, por tanto, sólo son visibles y utilizables en dicho método. Así mismo, permite crear clases a,iánimas.qut són
clases locales sin nombre. Las clases locales y las clases anónimas se usan de forma habitual en el trabajo con archivos
y en la creación de interfaces gráficas de usuario de las que se verán ejemplos en el Capítulo l O.
De esta forma, se puede escribir un programa para el cálculo genérico de un logaritmo como:
class LogGenerico {
static double x = // poner valor double
static double a= // poner valor double
3.6.1 Envoltorios
Los tipos predefinidos en el lenguaje Java son tipos simples, en el sentido de que no son clases. Por conveniencia,
existen unas clases predefinidas, denominadas envoltorios (wrappers, en inglés), para estos tipos simples. Estas
clases envoltorio proporcionan métodos de clase, útiles para convertir cadenas de texto al tipo adecuado, imprimir
con varios formatos, constantes estáticas con el valor mínimo y máximo del tipo, etc. Además, estas clases envoltorio
generan automáticamente una instancia cuando se usan tipos simples en contextos en los que se espera un objeto. Así
mismo, los envoltorios son compatibles con los tipos simples que representan, por lo que pueden usarse en expresio-
nes en que se espera el tipo simple. Los envoltorios definidos en Java pueden verse en la Tabla 3.1.
Los tipos byte y short se incluyen en el lenguaje Java por razones de eficiencia, por lo que no tienen envoltorios
predefinidos, utilizándose la clase Integer.
Todos los envoltorios disponen, entre otros, de los siguientes constructores y métodos:
Boolean boolean
Character char
Integer int
Long long
Float float
Oouble double
• Método que devuelve el valor primitivo. El nombre del método es la concatenación del tipo simple con la
palabra Value, es decir, charVa l ue() en el envoltorio Character, i ntVa l ue() en el envoltorio Integer, etc.
int m = miEntero.intValue():
En el siguiente ejemplo se muestra la posibilidad de mezclar tipos simples y envoltorios en expresiones matemá-
ticas realizándose la conversión entre ellos de forma automática.
public static void main(String args[J)
Integer envX = new Integer(7):
int y= 8:
double z:
envX += y; // añade y a envX
envX++; // incrementa en uno el valor de envX
z = Math.sqrt(envX): // rafz cuadrada de envX. z = 4.0
Esta conversión automática permite utilizar un tipo primitivo en el ámbito en que se requiere un objeto, por
ejemplo para añadir un entero a una lista de la clase ArrayList, como se verá en ejercicios del Capítulo 6.
Boolean
La única particularidad de Boo l ea n es que al convertir una cadena, se traduce la cadena "true" (cualquier combina-
ción de minúsculas y mayúsculas) al valor true. Cualquier otra cadena se traduce al valor false.
Character
El envoltorio Character proporciona métodos para determinar si un carácter es una letra o un dígito, espacio en
blanco(' ', '\t', '\n', '\ f' o '\r'), pasar de mayúsculas a minúsculas, etc. Existen algunas particularidades en estos
Programación en Java 2
métodos dependiendo del alfabeto al que pertenecen los caracteres. Java, como utiliza Unicode para codificar los
caracteres, permite otros alfabetos como el cirílico, griego, kanji, etc., cuyo comportamiento con las mayúsculas y
minúsculas puede diferir de los alfabetos occidentales derivados del latín. Asimismo, los dígitos para dichos alfabetos
también son diferentes de 'O', 'l', etc. Para estos detalles, consúltese un manual de referencia de Java.
Integer
Además de almacenar un valor i nt, se suele usar para los tipos predefinidos byte y short, ya que no tienen envoltorios propios.
Float y Double
En Java, los tipos fl oat y doub le pueden contener el valor +oo y el -oo, por ejemplo, en las divisiones por O. Pero también
algunas expresiones pueden dar lugar a valores que no representan un número, como por ejemplo Math. sqrt ( -1). Esto
en Java se representa con el valor NaN. Asimismo, existen métodos para determinar si un número es +oo, -oo o NaN.
float s= O:
s = 10 / s:
Float infinito= new Float(s):
3.6.2 Math
La clase Math contiene constantes y métodos de uso común en matemáticas. Todas las operaciones que se llevan a
cabo en dicha clase se realizan con tipo doub le. Contiene las constantes 1t (Math. PI) y el número de Euler, e (Math. E),
ambos de tipo doub le. En las funciones trigonométricas, los ángulos están en radianes y los métodos devuelven
valores doub le.
3.6.3 String
La clase Stri ng se usa para manejar cadenas de caracteres de cualquier longitud finita. Es una clase especial con
soporte específico incluido en el lenguaje Java. Para crear un objeto Stri ng no hace falta llamar al constructor, basta
escribirlo como un valor.
La clase String tiene un tratamiento particular en Java, pues aparte de la construcción de objetos a partir de
literales entre comillas, se pueden aplicar los operadores+ y+= que se usan para concatenar String.
Para comparar si los valores de dos Stri ng son iguales se utiliza el método equa 1s ().
Ampliación de clases
Ejercicio 3.1:
Math.
Escriba un programa que imprima en la pantalla las constantes de la clase
un punto y el nombre de la
Planteamiento: Para utilizar una constante de clase, se pone el nombre de la clase,
es, su valor no puede cambiar. La clase
constante. Las constantes son atributos calificados como final, esto
Euler, llamados Math. PI y Math. E.
Math proporciona dos constantes, el valor de 1t y el de la constante de
Solución:
import java.lang.Math:
Pi vale 3.141592653589793
E (cte de Euler) vale 2.718281828459045
Ejercicio 3.2:
es:
Escriba una clase de nombre Constantes que declare las siguientes constant
class PruebaConstantes {
Programación en Java 2
Aviso: Este programa adolece de un defecto: para acceder a las constantes hay que crear primero un objeto. Es
mejor declararlas como constantes de clase, como se vio en el Ejercicio 3.1, en el que las constantes de la clase
Math están disponibles sin necesidad de objetos. (Nota: además, Math está escrito de forma que no se pueden
crear objetos.)
Ejercicio 3.3:
Escriba un programa para representar el consumo de energía de una instalación eléctrica. Para ello, se
dispondrá de una clase que representa los aparatos conectados en la instalación. Cada aparato tiene un
consumo eléctrico determinado. Al encender un aparato eléctrico, el consumo de energía se incrementa en la
potencia de dicho aparato. Al apagarlo, se decrementa el consumo. Inicialmente, los aparatos están todos
apagados. Además, se desea consultar el consumo total de la instalación.
Hacer un programa que declare tres aparatos eléctricos, una bombilla de 100 watios, un radiador de 2000
watios y una plancha de 1200 watios. El programa imprimirá el consumo nada más crear los objetos. Poste-
riormente, se enciende la bombilla y la plancha, y el programa imprime el consumo. Luego se apaga la
plancha y se enciende el radiador y se vuelve a imprimir el consumo.
Planteamiento: Según el enunciado, la clase que modela a los aparatos eléctricos tiene dos datos, su potencia
y si están encendidos o no. Esta clase se llamará Apa ratoEl éctri co. Por otro lado, el consumo total debe ser un
atributo accesible a todos los aparatos eléctricos, lo que se consigue con un elemento de clase. Para ello, se
declara el atributo consumoTotal, de tipo double y se califica como static. Así, todas las instancias de
Apa ratoEl éctri co comparten el mismo atributo.
Para consultar el consumo total de la instalación, se proporciona un método que devuelva el valor de
consumoTotal. Este método ha de ser también de clase (calificado como static) y se llamará consumo().
Cuando un aparato eléctrico se enciende puede incrementar el consumoTata l con la potencia que consume.
Esto lo llevará a cabo el método enci ende ( ). Correspondientemente, cuando el aparato se apaga, se resta su
potencia al consumo total. Y de nuevo, sólo si estaba encendido. Esto se implementa en el método apaga ().
Evidentemente, hay que incrementar el consumo sólo si el aparato estaba encendido
Solución:
class AparatoEléctrico
Ampliación de clases
void enciende()
if ( ! encendido){ Al encender o apagar, sólo se
encendido= true: •~ - - - - - - - 1 1 modifica el consumoTata l si
consumoEléctrico += potencia: se cambia de estado.
void apaga()
if (encendido){
encendido= false:
consumoEléctrico -= potencia:
class ConsumoEléctrico
bombilla.enciende():
plancha.enciende():
System.out.println("El consumo eléctrico es "+
AparatoEléctrico.consumo ()):
plancha.apaga():
radiador.enciende():
System.out.println("El consumo eléctrico es"+
AparatoEléctrico.consumo ()):
Programación en Java 2
Aviso: El punto más delicado es olvidar que si se invoca el método enciende() dos veces seguidas, la segunda
no debe incrementar el consumo. Podría ser muy incómodo lanzar una excepción en ese caso. Por ello, el
método enciende ( ) sólo incrementa el consumo si el aparato estaba apagado. Correspondientemente, sólo se
decrementa el consumo si el aparato estaba encendido.
Ejercicio 3.4:
Añada a la clase Punto una constante llamada ORIGEN que sea el origen de coordenadas. La constante debe
ser accesible de forma estática. Escriba un programa, de nombre PruebaPunto, que determine la distancia de
los puntos (3,4), (0,4) y (2, -1) al origen usando la constante ORIGEN.
Planteamiento: Una constante es un atributo al que no se puede cambiar el valor una vez inicializado. Nor-
malmente, son atributos públicos de clase. En este caso, el valor constante es un punto situado en (0, 0). Para
declarar la constante se pone la palabra final delante de un atributo. El atributo no podrá cambiar de valor.
Como se desea que la constante esté disponible de forma estática, se antepone también la palabra stat i c. Así,
se podrá usar la constante escribiendo Punto. ORIGEN, sin necesidad de tener objetos de la clase Punto.
Solución:
class Punto
class PruebaPunto {
public static void main(String[J args) {
Punto pl = new Punto (3. 4):
Punto p2 = new Punto (O. 4):
Punto p3 = new Punto (2. -1):
Comenta~o: Es muy común declarar e inicializar las constantes simultáneamente. También es posible añadir
una sección donde se inicializan los miembros estáticos de una clase. Algunas clases de utilidad pública tienen
todos sus atributos y métodos declarados stat i c, para usarlos directamente sin crear objetos. Un caso de
ejemplo ya visto es la clase Math. La salida del programa es:
Ejercicio 3.5:
Escriba una clase llamada Elemento, que disponga de un atributo con su nombre. La clase debe contener un
método llamado númeroDeElementos que devuelve el número total de elementos que se han instanciado.
Planteamiento: Para determinar el número total de elementos, se crea un atributo de clase que se incrementa
cada vez que se crea una nueva instancia. Esto se hace en el constructor de Elemento. Además, se añade el
método de clase númeroDeEl ementos que lo devuelve.
Solución:
class Elemento
private String nombre:
Elemento(String nombre)
this.nombre = nombre:
Además de la construcción habitual
numElementos++; 4~---~, de un objeto de la clase, se actualiza
el atributo de clase numEl ementos.
Ejercicio 3.6:
Escriba una clase de nombre Ítem, que acepta un nombre en su constructor. Cada ítem debe disponer de un
número que servirá como identificador único de cada objeto. La clase Ítem dispondrá de un método para
obtener el identificador y otro para obtener el nombre. Haga un programa de prueba que genere tres ítems,
"uno", "dos" y "tres" y luego escriba los nombres e identificadores de cada ítem.
Planteamiento: La parte del atributo no presenta ningún problema. Para asignar un identificador único a cada
instancia de la clase, se proporciona un atributo de clase, que no es más que un contador de objetos construi-
dos. Además, se guarda el valor de ese contador en un atributo de cada objeto. Así, cada objeto recibe un
número distinto, único. Luego, el programa de prueba consiste en crear los tres objetos Ítem con nombres. Es
al acceder a los identificadores cuando se ve que cada uno ha recibido un número distinto.
Solución:
class Ítem
private static int contador= O:
Id= ++contador: 4
<o¡,----~1
Usamos un atributo de clase para
identificar a cada objeto de la clase.
int Id(){
return Id:
String nombre(){
return nombre:
Ítem uno id 1
Ítem dos id 2
Ítem tres id 3
Aviso: Como mecanismo de identificador de objetos, el sistema puede ser un poco pobre. Cuando los objetos
desaparecen, quedan números sin asignar que no se volverán a usar. Todos los objetos en Java reciben un
identificador único, pero basado en funciones de dispersión (hash function).
Ejercicio 3.7:
Se desea representar las bombillas que pueda haber en una casa. Cada bombilla tiene asociada un interrup-
tor y sólo uno. Así mismo, existe un interruptor general de la casa. Un interruptor tiene dos estados, ON y
OFF. Una bombilla luce si el interruptor general de la casa está ON y su interruptor asociado también.
Escriba una clase de nombre Bombilla que permita modelar la información anterior. Para ello, la clase
dispondrá de:
Planteamiento: Los interruptores se representan por los estados ON y OFF. Para ello, se usa un enumerado
con ambos valores, llamado Estado. Por otro lado, del enunciado se puede deducir que cada Bombi 11 a tendrá
un atributo que será su interruptor asociado. Ahora bien, el interruptor general es único y común para todas las
bombillas. Esto se modela como un atributo de clase (static) que comparten todos los objetos. Asimismo, el
método que pulsa dicho interruptor ha de ser de clase también. Por último, para el método que determina si la
bombilla luce o no, hay que tener en cuenta que tanto el interruptor de la bombilla como el interruptor general
deben estar a ON. Cuando uno de ellos esta a OFF la bombilla no luce.
Solución:
enum Estado { ON. OFF};
class Bombilla {
// Parte estátjca que representa al Interruptor General
prívate static Estado interruptorGeneral = Estado.OFF;
La parte común a todos los objetos
de una clase se representa con
public static void pulsalnterruptorGeneral(){ ~¿---~1 miembros de clase y se manejan
if (interruptorGeneral == Estado.ON){ con métodos de clase.
interruptorGeneral = Estado.OFF;
}else{
interruptorGeneral = Estado.ON;
public Bombilla() {
interruptor= Estado.OFF:
al.pulsalnterruptor():
System.out. println( "al " + (al. luce() ? "SI" "NO") + " luce."):
al.pulsainterruptorGeneral():
System.out.println("al " + (al. luce() ? "SI" "NO") + " luce."):
Comentario: Los métodos que pulsan el interruptor {tanto el general como el de la bombilla) comprueban el
estado para cambiarlo, mediante un i f (o un switch).
Si se modela el estado del interruptor con un booleano, llamado está Pulsado, el método pulsar se
reduce a:
Aviso: No sería correcto en este problema representar los interruptores como boo lean. Es cierto que cada
interruptor sólo dispone de dos estados, así como el tipo boo lean tiene sólo dos valores. Pero las operaciones
sobre el interruptor no son las que se dispone de los boolean.
Ejercicio 3.8:
Escriba un programa que utilice la clase Bombilla del apartado anterior. Para ello, se creará una Bombilla
y se imprimirá por pantalla si luce o no. Luego se pulsa el interruptor de la Bombilla y se vuelve a imprimir
el estado de la misma. Por último, se pulsa el interruptor general y se imprime el estado.
AmpHaclón de clases
Planteamiento: Se define una clase pruebaBombi l la. Primero instancia una Bombilla, llamada al. Como los
interruptores pueden tener el valor ON y OFF, con el operador temario "?:" se imprimen las palabras
"SI" 0
"NO" para determinar si lucen.
Solución:
class PruebaBombilla
al.pulsalnterruptor():
System.out.println("al "+ (al.luce() ? "SI" "NO") + • luce."):
al.pulsainterruptorGeneral():
System.out.println("al " + (al. luce() ? "SI" "NO")+" luce."):
al NO luce.
al NO luce.
al SI luce.
PAQUET ES
Ejercicio 3.9:
Se desea realizar una biblioteca de clases para el tratamiento de imágenes, vídeo y audio para la realización
de aplicacion es multimedia. Como existirán multitud de formatos de imágenes, vídeo y sonido, se estructuran
las distintas clases en un paquete, llamado mediaBib. Se agruparán los posibles codificadores y decodificad
ores
en tres subpaquetes:
Y, para cada uno de los formatos, se proporcion ará una clase que pueda codificar y decodifica r dichos
formatos. El nombre de esta clase será "codecFormato", sustituyend o "Formato" por el tipo tratado,
por
ejemplo, codecG/F, codecGSM, etc.
Se pide diseñar la estructura de directorios necesaria para la biblioteca, indicando los directorios
y
ficheros necesarios. Asimismo, para cada fichero se debe escribir la declaración pertinente respecto
de la
pertenenci a al paquete. NO SE PIDE que se codifiquen las clases, sólo la informació n de estructura.
codecMPEGl.java y codecMPEG4.java. Por último, en la carpeta audio se pondrán los ficheros codecGSM. java y
codecMP3. java.
Solución:
La estructura de directorios se muestra a continuación:
Cada fichero debe contener al principio una línea indicando el paquete al que pertenece y luego las clases que
aporte. La siguiente lista recoge sólo las líneas de declaración de paquete:
Comentario: Evidentemente, cada fichero tendrá, al menos, una clase pública con el mismo nombre que el
fichero. Los detalles de codificación exceden del propósito de este libro, pero Java Media Framework (JMF) es
una biblioteca que cubre estos aspectos.
Aviso: Tenga en cuenta que para la clase que trata el formato H.263 se ha elegido el nombre codecH263. No se
puede usar codecH. 263, porque los identificadores de clase no pueden llevar un punto. Esto es así porque el
punto es el separador para paquetes y generaría ambigüedad un nombre como medi aBi b. vi deo. codecH. 263.
Tampoco se admiten caracteres como el guión ' -'. Por razones parecidas, se suelen evitar las peculiaridades de
internacionalización, y se suelen evitar acentos y eñes, que sí están admitidos.
CLASES PREDEFINIDAS
Ejercicio 3.10:
Escriba un programa que inicialice dos cadenas de caracteres, una llamada nombre y otra llamada apellido.
Los valores iniciales de las cadenas son "Juan" y "Pérez", respectivamente. El programa debe escribir ambas
cadenas y su longitud por pantalla.
Planteamiento: Se declaran dos referencias a Stri ng, y se inicializan directamente, asignando la cadena de
caracteres sin necesidad de new, en la misma línea. Para conocer la longitud de una cadena de caracteres, se usa
el método l ength ( ) .
Solución:
class Cadenasl
AmpUación de clases
Ejercicio 3.11:
Escriba un programa que declare una cadena de caracteres denominada nombre, con
primerApellido, con valor "Pérez" y segundoApellido con valor "Lópei'. Después, el programa
nombre el primer apellido y luego el segundo. Por último, el programa imprime el nombre c01noteto
Planteamiento: Para concatenar dos cadenas, se usa la operación"+". También existe la Vaíiifflttcn+';;>;iJ
hacer el programa, se crean las tres variables nombre, pri merApe l l ido y segundoApe 11 ido, 1ruc1atiz1i~~ ,GJí;IO
indica el enunciado. Luego se concatena con nombre con pri merApe l l ido con el operador "+=''.
segundoApe l l ido. Por último, se imprime el nombre y el número de letras.
Solución:
class Cadena2
nombre+= primerApellido:
nombre+= segundoApellido:
Comentario: Se podría resolver en una sola sentencia la concatenación de los dos apellidos, de la forma:
Ejercicio 3.12:
programa ha de imprimir por pantalla
Haga un programa que contenga la cadena "Juan Piñón Lópei'. El
en mayúsc ulas.
ambas cadenas con todos los caracteres en minúsculas y luego
y toUpperCase() que devuelven una
Planteamiento: La clase Stri ng proporciona dos métodos, tolowerCase ()
cadena con todos los caracteres en minúsculas y en mayúsculas.
Solución:
class Cadenas3
Ejercicio 3.13:
pasados en línea son iguales o no.
Escriba un programa que determine si los dos primeros argumentos
comparar cadenas, se usa el método
Planteamiento: Los dos primeros argumentos son args[OJ y arg[l]. Para
equa l s ( ) que devuelve un booleano indicando si son iguales.
Solución:
class Cadena4
if ( args[OJ.compareTo(args[l]) ==O){
System. out. println( "Son iguales."):
}else{
System. out .println( "NO son igual es."):
Aviso: Un error muy común es usar el operador "==" para comparar objetos. Los objetos son referencias, es
decir, al comparar con "==" se está evaluando si las referencias apuntan al mismo sitio. El caso de Stri ng es
más delicado porque, por razones de eficiencia, las cadenas con el mismo valor apuntan al mismo objeto. El
siguiente programa:
if (sl = s2) {
System.out.println("Son iguales."):
} else {
System.out.println("NO son iguales."):
imprime por pantalla el mensaje "Son igual es . ", con lo que parece que "==" funciona bien. Se aconseja usar
siempre el método equa 1s ( ).
Aviso: En este programa habría que comprobar que el array de argumentos tiene al menos dos.
Ejercicio 3.14:
Escriba un método que dado un objeto de la clase String cuente diferentes tipos de caracteres. En particular,
el método imprimirá el número de letras, dígitos y espacios en blanco de la cadena. Haga un programa que
escriba el conteo de la cadena "Hola, vivo en Marquina 123, 5-7").
Planteamiento: El envoltorio Character tiene funciones que trabajan sobre caracteres. Se usarán los
métodos i sletter(), i sOigit() e i sWhitespace() para comprobar el tipo de un carácter. Para examinar
cada carácter del Stri ng, se recorre con un bucle for. Pero el bucle for espera una secuencia de un tipo
base. Con el método toCharArray() de la clase Stri ng, se puede obtener un array de caracteres a partir de
un Stri ng.
Valor de retomo: El método escribe en pantalla, por lo que el valor de retomo se especifica como voi d.
Solución:
class Contarletras
static void conteo (String s)
int numletras = O:
int numDígitos = O;
int numEspacios = O:
Programación en Java 2
etras):
System.out.println ("Número de letras "+ numl
tos" + numO ígitos):
System.out.println ("Número de dígi
ios "+ numE spacios):
System.out.println ("Número de espac
como sigue:
Comentario: La salida del programa quedaría
Número de letra s 18
Número de dígitos 5
Número de espacios 5
) de la clase
a sería utilizando el método charAt(int index
Otra forma de hacer el recorrido por la caden
. El bucle se escribiría así:
String, que devuelve el carácter en la posición index
4,1(-----------[[
for (int i = O: i < s.length(); i++)
{
RecorridoconcharAt enelString. ))
char c = s.charAtO:
if (Character.isletter(c))
numletras++:
}else if (Character.isDigit(c)) {
numOígitos++;
}else if (Character.isWhitespace(c)) {
numEspacios++:
y de legib ilidad .
Esto no suele usars e por razon es de efici encia
Solución:
String sustituye (String s)
s = s.replace('e', 'a');
s = s.replace('i'. 'a'): +-----------11EJoibietoorioirnaln<>sem0<lffic.:1. II
s = s.replace('o'. 'a'):
s = s.replace('u', 'a');
return s;
Aviso: Sólo hay que tener cuidado con no sustituir la vocal 'a', pues es innecesario. El método no sustituye
letras acentuadas, etc.
Ejercicio 3.16:
Escriba un método que, dada una cadena de caracteres, devuelve la mitad inicial de la cadena. Escriba un
programa que pruebe el método con las cadenas "Hola que tal" y "Adiós".
Planteamiento: El método substri ng( i ni ci o. final) toma dos números y devuelve una cadena que comien-
za en inicio y termina en final. Las cadenas comienzan en O, y length()/2 da el punto medio. Luego se
escribe un ma in ( ) para probar con las cadenas propuestas por el enunciado.
Solución:
class ParteAlMedio {
s = "Adiós":
System.out.println(s +" "+ parteAlMedio(s)):
hola q
Ad
Programación en Java 2
Ejercicio 3.17:
sustituya todas las ocurrencias del texto "es" por
Escriba un método que, dada una cadena de caracteres,
los grupos de dígitos por un único carácter asteris-
"no por". Escriba un segundo método que sustituya todos
ueno9 00" el prime r método debe devolver "no
co, es decir, si la cadena de caracteres es "estol 234es 5678b
er "esto*es*bueno*". Escriba el programa que
portol 234no por5678bueno900" y el segundo debe devolv
permita comprobar que funciona correctamente.
una expresión regular y la cadena porla que desea
Plante amien to: El método rep lace (Stri ng. Stri ng) toma
el primer parámetro se utiliza una cadena de caracte-
sustituir cualquier ocurrencia de la expresión regular. Si
res se tomará como tal cuando coincida completamente.
os, por tanto el parámetro será de la clase
Parámetros: La cadena sobre la que se quiere aplicar los cambi
String.
Solución:
public class UsoString
public static String cambiaDigitos(String texto){ Utiliza una expresión regular que
return texto. replaceAll( "\ \d+". "*"); ...,"-- --11 significa un dígito o más.
System.out.println(cambiaEs(textoüriginal)):
System.out.println(cambiaDigitos(textoüriginal)):
no porto1234no por5678bueno900
esto*es*bueno*
Parámetros: La cadena en la que se quiere contar cuántas veces aparece el texto y el texto que se quiere
buscar. Por tanto, se necesitan dos objetos de la clase Stri ng.
Valor de retomo: El número de veces que aparece el segundo argumento en el primero, es decir, un valor del
tipo int.
Solución:
public class UsoString
return veces;
Ejercicio 3.19:
Escriba un método que cuente el número de palabras que contiene un texto.
Planteamiento: Para contar el número de palabras se puede utilizar de la clase String el método split() que
permite dividir una cadena de caracteres en fragmentos de acuerdo con una expresión regular, devolviendo un
array de String con todos los fragmentos del texto original. Para dividir por palabras, se utiliza como expresión
regular " +", un espacio y un signo más, que significa un espacio una o más veces. Antes de llamar a sp l i t ( ) se
llamará al método trim() para eliminar los espacios en blanco que pueda haber al principio y al final del texto.
Valor d.e retomo: El número de palabras de la cadena de caracteres, es decir, un valor del tipo i nt.
Solución:
public class UsoString
e no puedo acordarme"));
cuentaPalabras("En un lugar de la mancha. de cuyo nombr
Solución:
import java.util.GregorianCalendar:
import java.util.Calendar:
if (gc.get(Calendar.OAY_OF_WEEK) = Calendar.MONDAY)
{
cuentalunes++:
) +
System.out.println("El "+ gc.get (Calendar.DAY_OF_MONTH
"/" + (gc.get (Calendar.MONTH)+l) + ""'. ,_ _ _ ___,
"/" + gc.get (Calendar.YEAR) + 1
" es l unes" ) : Los meses se representan desde O
(enero) a 11 (diciembre).
El 4/4/1966 es lunes
El 4/4/1977 es lunes
El 4/4/1983 es lunes
El 4/4/1988 es lunes
El 4/4/1994 es lunes
El 4/4/2005 es lunes
El cumpleaños se celebra en 6 lunes
Ampliación de clases
Aviso: El bucle for primero incrementa el año (método ro 11) porque se considera que el día de nacimiento no
se celebra el cumpleaños.
Hay que tener cuidado con los meses, pues Calendar considera el Ocomo enero y el 11 como diciembre. Si
se escribe GregorianCalendar(l965. 4. 4), se especifica el 4 de mayo de 1965.
Ejercicio 3.21:
Escriba un método que dado un ángulo en radianes, lo escriba en pantalla en grados, así como los valores del
seno, el coseno y la tangente. Las funciones de Math han de importarse de forma estática. Haga un programa
que imprima los valores de esas tres funciones para los valores O, 11f4, 1t:/2, y 11: en radianes.
Planteamien to: Al importar de forma estática, no se requiere anteponer el nombre de la clase. Entonces se
importa toda la clase Math. El ángulo, cuando no se dice nada, se supone que está en radianes. El método
toDegrees ( ) lo pasa a grados.
Valor de retorno: El resultado del método es escribir en pantalla. El método no necesita devolver ningún valor
de retorno por lo que se utiliza la cláusula voi d.
Solución:
Importación estática de todos los
import static java.lang.Math.*; 1,~---~1
métodos de la clase Math.
public class Trigonometría {
Aviso: El código queda más simple, pero no siempre mejora la legibilidad del programa, porque se olvida de
dónde proceden los métodos.
Estructuras de control
4. 1 ESTRUCTURAS DE SELECCIÓN
4. 1. 1 Estructura i f
La estructura i f se escribe de la siguiente forma:
if (condición)
sentencias
La condición se escribe siempre entre paréntesis. La condición es una expresión que evalúa un valor de tipo
boolean (booleano) como las expresiones aritmético-lógicas vistas en el Capítulo l. Si la condición devuelve se
ejecuta el conjunto de sentencias dentro del bloque del i f.
Un bloque de sentencias está delimitado por llaves, por lo que la estructura i f está asociada a todo el bloque de
sentencias. Si la estructura i f lleva asociada sólo una sentencia, se puede poner sin llaves, pero ,~:rec~ll;li!:!Q~a
añadirlas aunque sea redundante. Esto mismo es aplicable al resto de estructuras que se describen en las siguientes
secciones.
Por ejemplo, suponga que en un programa existe una variable velocidad de tipo i nt cuyo
if (velocidad<= 90){
System.out.println("La velocidad es menor o igual que 90.");
Como la condición vale true, se escribe por pantalla el mensaje de la sentencia dentro del blpque if.
4. 1. 2 Estructura i f-e l se
La estructura i f-e l se se escribe de la siguiente forma:
if (condición)
sentencias
Programación en Java 2
} else {
sentencias
, es decir, se evalúa
La condición es una expresión lógica como en la sección anterior. Si la condición es verdadera
continuac ión del i f. Seguidamente, el
a true, se ejecuta la sentencia o bloque de instrucciones que se encuentra a
mente posterior a toda esta estruc-
programa continuaría su ejecución de forma secuencial con la sentencia inmediata
o el bloque de sentencia s que se
tura. Si, por el contrario, la condición se evalúa a false, se ejecuta la sentencia
encuentra a continuación del e1se y el programa continuaría su ejecución.
valor es 110:
Por ejemplo, suponga que en un programa existe una variable velocidad de tipo int cuyo
if (velocidad<= 90) {
System.out.println("La velocidad es menor o igual que 90."):
} else {
System.out.println("Velocidad excesiva. Supera los 90."):
4. 1. 3 Operador condicional
la condición a la izquier-
El operador condicio nal(?:) está relacionado con la estructura i f-el se. El operador evalúa
haya entre el? y el : . Si la condición
da del símbolo? . Si la condición vale true devuelve el valor de la expresión que
para escribir el mayor de tres números
vale false se devuelve el valor de la expresión tras el símbolo : . Por ejemplo,
se puede escribir.
switch (expresión){
case valorl:
sentencias:
break:
case valor2:
case valor3:
sentencias:
break:
default:
sentencias:
break:
Estructuras de control
La expresión, que es obligatorio que esté entre paréntesis, tiene que evaluarse a un
rado o un boolean. A continuación, en cada case aparece un valor que únicamente
es decir, una expresión cuyo valor se puede conocer antes de empezar a ejecutar el
expresión del switch. Después de cada case se puede poner una única sentencia o un
asociados en cada case se comparan en el orden en que están escritos. Cuando se
sentencias se utiliza la sentencia break que hace que el control del programa termine e
la sentencia que se encuentre después de esta estructura. Si no coincide el valor de ningún
expresión, se ejecuta la parte default.
Si ningún valor de los case coincide con el resultado de la expresión y la parte default
opcional, no se ejecuta nada de la estructura switch.
Por ejemplo, suponga que desea conocer el número de días de un mes dado. Un switch es
seleccionar cómo calcular cuántos días le corresponden a cada mes.
System.out.println("El mes " +mes+ " tiene " +días+ " días.");
4. 2 ESTRUCTURAS DE REPETICIÓN
4. 2. 1 Estructura whi 1e
La estructura de repetición whi le sigue el siguiente esquema:
while (condición){
sentencias
Programación en Java 2
la condi-
La condición tiene que estar obligatoriamente entre paréntesis. La condición es una expresión lógica. Si
la ejecución de las instruccion es
ción vale true, se ejecutan las sentencias que componen el bucle. Cuando concluye
a ejecutar las instruccion es
del bucle se vuelve a evaluar la condición. De nuevo, si la condición es cierta se vuelven
el programa
del bucle. En algún momento la condición valdrá false, en cuyo caso finaliza la ejecución del bucle y
continúa ejecutándose por la sentencia que se encuentre a continuación de la estructura whi le.
primo.
Por ejemplo, el siguiente método devuelve true si el número introducido por parámetro es un número
return primo:
4. 2. 2 Estructura do-whi le
La sentencia do-whi le tiene la siguiente estructura:
do {
sentencias
} while (condición);
la
Cuando en un programa se llega a una estructura do-wh i l e se empiezan a ejecutar las sentencias que componen
vale true, se ejecutan de nuevo las
estructura. Cuando se terminan de ejecutar se evalúa la condición. Si la condición
vale false.
sentencias que componen la estructura. El bucle deja de repetirse cuando, tras evaluarse la condición, ésta
Como ocurría con la estructura whi le es necesario que dentro del bucle, en algún momento, la condición valga false
para evitar que el bucle se ejecute indefinidamente.
Al
Suponga que se desea realizar un programa que solicite al usuario un número entre O y 100, ambos inclusive.
introducido no está dentro del intervalo,
terminar debe imprimir por pantalla el número introducido. Si el número
debe dar un mensaje de error. Un posible programa sería el que se muestra en el siguiente ejemplo:
import java.util.Scanner:
do {
System.out.print("Introduzca un número entre O y 100: ");
Estructuras de control
numero= teclado.nextlnt():
} while (numero< O 11 numero> 100):
4. 2. 3 Estructura for
La estructura for tiene dos formas. La más habitual es:
.. La i ni ci ali zaci ón es una sentencia que permite inicializar el bucle, puede ser la
de las variables que se utilizan en el bucle. Esta sentencia de inicialización se ejecuta ún!ícairneitttt':l
la primera ejecución del bucle.
.. La candi ci ón es la condición para continuar la ejecución del bucle. La condición se evaláa
empezar a ejecutar el bucle. Si la condición es cierta, se ejecutan las sentencias del
.. Después de ejecutar las sentencias del bucle y antes de volver a evaluar la condición se ejecuta la
ci ón. Esta parte se suele utilizar para modificar el valor de las variables que forman parte dé la ce1!1di1bi~1n.
Todos los elementos que se acaban de describir del bucle for son opcionales, es decir, pueden
ejemplo, para escribir por pantalla 5 veces el mensaje "Hola a todos" con el número de vez, se puede escribir:
donde la variable indicada entre paréntesis, que se puede declarar en ese mismo lugar, va toman~o el v~or de tpdas
las variables de la estructura indicada, repitiéndose el bucle para todos los valores. Por ejemplo, para escribir por
pantalla todos los elementos de un array de String se puede escribir:
for(String a : miArrayDeString){
System.out.println(a):
Programación en Java 2
4.4 EXCEPCIONES
4.4. 1 Captura
La estructura de captura de excepciones es try-catch-fi na l ly.
try {
sentencias
catch (ClaseException e) {
sentencias
catch (ClaseException e)
Estructuras de control
sentencias
catch (ClaseException e)
sentencias
finally {
sentencias
En la estructura try-catch-fi na l ly, la parte catch puede repetirse tantas veces como excepciones di:fei;entes se
deseen capturar. La parte fina 11 y es opcional y sólo puede aparecer una vez.
Para ver cómo funciona esta estructura en el siguiente ejemplo se presenta un programa que pide al Wl
número entre Oy 100, con manejo de excepciones.
import java.io.*;
do {
try{
System.out. print( "Introduzca un número entre O y 100: ");
linea = teclado.readline();
numero= Integer.parseint(linea);
}catch(IOException e){
System.out.println("Error al leer del teclado.");
}catch(NumberFormatException e){
System. out. pri nt l n( "Debe introducir un número entero entre Oy 100. ");
}finally{
intentos++;
En este programa se pide repetidamente un número utilizando una estructura do-whi le, mientras el número sea
menor que Oo sea mayor que 100. Dentro de esta estructura do-whi le es donde se solicita el número al usuario. El
método readl i ne() de la clase BufferedReader puede lanzar la excepción IOExcepti on. Si no se hace nada con ella,
cuando se produce el programa termina. Así mismo, la llamada al método parseint() puede lanzar la excepción
NumberFormatException. Esta excepción se lanza cuando parseint() no puede convertir el texto en un número
entero.
Cuando se produce una excepción se compara si coincide con la excepción del primer catch. Si no coincide se
compara con la excepción del segundo catch, y así sucesivamente. Cuando se encuentra un catch cuya excepción
coincide con la que se ha lanzado, se ejecuta el bloque de sentencias de ese catch.
Programación en Java 2
Si ningún bloque catch coincide con la excepción lanzada, dicha excepción se lanza fuera de la estructura
try-
catch- fina 11 y. Si no se captura en el método, se debe lanzar delegándola. Para ello debe declararlo en la cabecera del
método.
El bloque f i na 11 y se ejecuta tanto si t ry terminó normalmente como si se capturó una excepción en algún
bloque
catch. Es decir, el bloque final l y se ejecuta siempre.
4.4.2 Delegación
Se produce una delegación de excepciones cuando un método utiliza una sentencia que puede generar una
excepción,
pero la excepción que se puede generar no la captura y la trata, sino que la delega a quien le llamó.
Para ello,
simplemente, declara en la cabecera que la excepción que se puede producir durante la ejecución del método
la puede
generar dicho método de la siguiente forma:
De esta forma si al leer del Buffered.Reader que recibe en el parámetro se encuentra con algo que no es
un entero,
se generará una excepción y en lugar de devolver el entero, se enviará la excepción a donde se llamó a
este método.
Al crear la excepción, se ha añadido un constructor que acepta un String. De esta forma se puede
añadir un
mensaje al crear la excepción que dé detalles adicionales sobre el problema que ha generado la excepción.
A partir de
este momento se dispone de una excepción que se puede lanzar cuando sea necesario.
try {
alumno.ponAñoDeNacimiento(unAño);
catch (AñoFueraDeRangoException e) {
//manejarla excepción de poner el año
4.5 ASERCIONES
4.5.1 Aserciones como comprobación de invariantes
Una aserción tiene la siguiente sintaxis:
assert condicion;
donde la condición es una expresión lógica que debe cumplirse en el momento en que se
condición no se cumple, el programa termina con un error. Tras el operador dos puntos puede.pon~~ un Sttmg .con
el mensaje que se devuelve como error.
Sin embargo, en un método no público sí se puede sustituir esa comprobación, en muchos casos redundante, por
una comprobación que asegure que el método se utiliza de forma consistente en la clase, como en el siguiente ejemplo.
Si al llamar al método fijalntervalo(), el valor del parámetro no está dentro del intervalo establecido, al no
cumplirse la condición de la aserción, el programa terminará con un error.
El método anterior es un método de ordenación de números enteros. Al finalizar el método debe asegurarse que el
array termina con todos sus datos ordenados. Como esta comprobación es compleja se ha añadido unas líneas de
código que hacen la comprobación. En la aserción se ha utilizado la versión completa, en la que si la condición no se
cumple, se evalúa la parte que hay tras los dos puntos y con ello se construye el error AsertionError. Cuando el
programa termina, aparecerá en pantalla el mensaje que se ha puesto tras los dos puntos.
ESTRUCTURAS DE SELECCIÓN
Ejercicio 4.1:
Escriba un método, de nombre mayorDeEdad, que reciba una edad como entero por parámetro y muestre un
mensaje por pantalla si es mayor de edad o no.
Planteamiento: El método debe escribir "La persona es mayor de edad" o "La persona no es mayor de edad".
Se utilizará la estructura i f para añadir dentro del mensaje de salid