Академический Документы
Профессиональный Документы
Культура Документы
Introduccin
Este curso introduce a los alumnos a la solucin de problemas por medio del diseo y la
programacin orientada a objetos. El nfasis est en el anlisis del problema y el diseo de
la solucin, la documentacin y la implementacin. Los alumnos utilizan bibliotecas
comerciales de software, y crean proyectos de software. Los ejercicios de programacin se
llevan a cabo en Java.
Libro
Barker, Jacquie. Beginning Java Objects: From Concepts to Code. Primera Edicin,
Apress, 2000.
o
Barker, Jacquie. Beginning Java Objects: From Concepts to Code. Segunda
Edicin, Apress, 2005.
Las tareas de lectura se indican dentro del contenido del curso. Adems, una lista
completa se encuentra en Apndice D. Lecturas.
Requerimientos de Software
Producir
1. Programas de java que exhiban elementos de programacin orientada a
objetos, incluyendo herencia, polimorfismo, clases abstractas e interfaces
2. Clases de Java robustas utilizando excepciones y modificadores de acceso
3. Diseos orientado a objetos utilizando UML
4. Implementaciones de Java a partir de una especificacin
5. Extensiones a programas de Java existentes para mejorar el desempeo o
aadir funcionalidad
6. Cdigo con calidad profesional aplicando convenciones de cdigo utilizados
en la industria
II.
III.
IV.
Utilizar
1. Herramientas profesionales comnmente utilizadas tales como depuradores
(debuggers), ambientes de desarrollo (IDE), y editores de UML
2. Clases y paquetes utilitarios que involucran E/S (I/O), y tokenizacin
3. Clases de Java Swing para implementar Interfaces Grficas de Usuarios
(GUI)
4. Recursos en lnea para mantenerse al corriente de los desarrollos de Java
5. Patrones de Diseo
6. Casos de prueba para la prueba de unidades (unit testing)
7. Colecciones e iteradores
Discutir de Manera Informada sobre
1. Conceptos avanzados de orientacin a objetos
Posicionarse como Programador de Java
Al completar exitosamente este curso, el estudiante ser capaz de (a) llevar a cabo
tareas de programacin tales como extender la funcionalidad de programas
existentes y mejorar el desempeo de mdulos de programas existentes, (b)
implementar Interfaces Grficas de Usuario (GUI) en Java, (c) implementar
programas que exhiban un comportamiento especificado, y (d) depurar y corregir
programas que no se comportan de acuerdo a una especificacin.
Applets en Java
Aplicaciones en Java
Lecturas:
Requeridas:
o Barker, primera edicin, captulo 1 (pginas 137).
o Barker, segunda edicin, captulo 2 (pginas 1532).
Secuencia: Leer el libro de texto antes de leer esta pgina.
Applets en Java
Los programas de Java se presentan en muchas variantes: applets, servlets y aplicaciones.
Los applets son referenciados desde las pginas Web e interpretadas por navegadores Web.
Cada applet contiene una clase pblica que extiende la clase Applet.
El siguiente es un applet que genera un mensaje como salida:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
import java.applet.*;
import java.awt.*;
public class MyApplet extends Applet {
public void paint(Graphics g) {
g.drawString("This is an applet!\n", 10, 10);
}
}
Listado 1 MyApplet.java
Aplicaciones en Java
Las aplicaciones de Java son programas "autnomos", interpretados por un intrprete de
Java (no por un navegador Web) sobre un sistema anfitrin. Para ejecutar una aplicacin de
Java, el usuario escribe un comando que invoca el intrprete de Java en la aplicacin
especificada.
main(String[]
args)
El mtodo main tiene un parmetro de entrada, un arreglo String que contiene argumentos
de lnea de comando que el usuario puede haber especificado al teclear el comando java.
Los argumentos de lnea de comando permiten al usuario pasar informacin a la aplicacin.
No utilizaremos argumentos de lnea de comando en este curso.
La siguiente es una aplicacin simple que despliega las palabras en la pantalla: "This is
my first application!" ("sta es mi primera aplicacin!").
1: public class MyApplication {
2:
3:
public static void main(String[] args) {
4:
5:
System.out.println("This is my first application!");
6:
}
7: }
Listado 2 MyApplication.java
La clase que contiene el mtodo main debe ser public. La declaracin de clase puede o no
tener una clusula extends; en este aspecto, las aplicaciones difieren de los applets. Los
nombres de clases deben tener la primera letra de cada palabra en maysculas y no deben
contener ningn guin bajo ( _ ). Por ejemplo, el nombre WordCount cumple con la
convencin, mientras que wordCount, wordcount y word_count no lo hacen. El archivo
que contiene el cdigo fuente debe tener el mismo nombre que la clase que contiene y usar
la extensin .java. Por ejemplo, el archivo que contiene la clase WordCount debe ser
nombrado WordCount.java.
La siguiente figura muestra la salida de la clase MyApplication.
Introduccin
Crear el Proyecto
Crear la Clase
Compilar la Clase
Ejecutar la Aplicacin
Introduccin
Un Ambiente Integrado de Desarrollo (Integrated Development Environment o IDE por sus
siglas en ingls) es una herramienta utilizada por los desarrolladores de sistemas para
ayudarlos durante las diferentes fases del desarrollo de sistemas. Eclipse es un IDE de
cdigo abierto (open source) que soporta muchos lenguajes de programacin. Eclipse viene
con un Ambiente de Desarrollo de Java (Java Development Environment o JDE) que
incluye un editor de resalte de sintaxis, un compilador, un depurador, un navegador de
clases y un administrador de archivo/proyecto. La funcionalidad de Eclipse puede ser
extendido con plug-ins tales como plug-ins de UML para modelacin Orientada a Objetos.
En esta pgina, te mostraremos cmo crear y ejecutar la aplicacin MyApplication.
Crear el Proyecto
El primer paso es crear un proyecto de Java:
1. En el men File (archivo), apunta a New (nuevo) y despus haz un clic en Project
(proyecto).
2. En el asistente de New Project (nuevo proyecto), presiona Java en el panel
izquierdo, selecciona Java Project (proyecto de java) en el panel derecho y despus
da un clic en Next (siguiente).
Crear la Clase
1. En el men File (archivo), apunta a New (nuevo) y da un clic en Class (clase).
2. En el asistente de Nueva Clase de Java o New Java Class, escribe MyApplication en
el cuadro Name (nombre) y despus selecciona Finish (terminar).
Compilar la Clase
Eclipse incluye un compilador de Java incremental. Cuando introduces una lnea de cdigo
que contiene un error, el editor desplegar, en la derecha, una marca roja junto a dicha lnea
de cdigo.
1. Introduce un error de sintaxis borrando el punto y coma ( ; ) al final de la lnea que
contiene System.out.println. El editor desplegar una marca roja.
2. Apunta sobre la marca roja para desplegar el mensaje de error.
Ejecutar la Aplicacin
1. Comienza por crear una configuracin inicial para el proyecto MyApplication. Da
un clic en MyApplication en la vista Projects (proyectos), presiona la flecha a la
derecha del botn Run (ejecutar) en la barra de herramientas y despus presiona
Run....
Introduccin
Paquetes y el Estatuto import
La Clase java.lang.String
La Clase java.util.StringTokenizer
Las Clases de Envoltura (Wrapper Classes)
Introduccin
El API (Interfaz de Programacin de Aplicaciones o Application Programming Interface)
de Java representa una librera de Java extensiva. Estas libreras son escritas
cuidadosamente, son robustas y estn probadas exitosamente.
La documentacin del API de Java es generada por la herramienta Javadoc. Javadoc
produce un conjunto de pginas HTML a partir de los comentarios Javadoc de un archivo
fuente de Java. Los comentarios Javadoc documentan las clases, variables y mtodos de
una aplicacin. Utilizaremos comentarios Javadoc en nuestro cdigo fuente para que la
documentacin de nuestras aplicaciones cuente con la misma organizacin y formato que el
API de Java.
El nombre completo calificado de una clase que es parte de un paquete es el nombre del
paquete y el nombre de la clase, separados por un punto.
java.util.GregorianCalendar
import java.util.GregorianCalendar;
Esto resulta ms conveniente, debido a que el nombre del paquete debe ser mencionado
slo una vez en el estatuto import. Continuamente, los programadores utilizan muchas
clases del mismo paquete. En vez de utilizar un estatuto import para cada clase, se importa
el paquete completo:
import java.util.*;
El asterisco (*) acta como un comodn, que representa a todas las clases del paquete
especificado.
El asterisco es conveniente. Por ejemplo, considera una aplicacin que utiliza el asterisco
para importar todas las clases del paquete java.io, pero utiliza slo una. El nuevo cdigo
que utilice otras clases de java.io puede ser agregado sin aadir ms estatutos import.
Muchos programadores utilizan el asterisco, an cuando requieren slo una clase de un
paquete, porque es rpido de escribir y no incurre en ninguna sobrecarga: importar un
paquete no disminuye la velocidad de compilacin o ejecucin, ni incrementa el tamao del
cdigo de bytes.
Finalmente, el paquete java.lang es implcitamente importado en todas las aplicaciones de
Java, de modo que nunca existe la necesidad de importar java.lang. Todas las
aplicaciones pueden hacer referencia a clases del paquete java.lang utilizando sus
nombres simples.
Para cada una de las clases presentadas a continuacin, se te proporciona una liga a su
documentacin API. Te alentamos a seguir estas ligas para que te familiarices con los
muchos mtodos tiles que tienen estas clases.
La Clase java.lang.String
Debido a que Java no provee un tipo string primitivo, la clase java.lang.String se utiliza
mucho. Java incluye la literal de la clase String, una secuencia de caracteres entre comillas
dobles, tales como "abc". Una literal de la clase String es una instancia de la clase String.
La siguiente es una lista de algunos mtodos definidos en la clase String:
String(). Construye un nuevo objeto String que representa una secuencia vaca
de caracteres.
String(String original).
int length().
especificado.
int indexOf(String
String.
str).
si anObject representa
especificado.
"hola " + 5
Sin una traduccin automtica, tendramos que escribir:
"hola " + (new
Integer(5)).toString()
Debido a que el smbolo ms ( + ) es tambin utilizado para sumar, por lo menos uno de sus
operandos debe ser un String para que funcione como operador de concatenacin.
Observa lo siguiente:
stdOut.println(2 + 3 + "5"); // imprime 55, no 235
stdOut.println(2 + "" + 3 + "5"); // imprime 235
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
El archivo StringClassDemo.java
PrintWriter
stdOut = new
PrintWriter(System.out, true);
/**
* Mtodo principal, muestra el uso de la clase String
*
* @param args no utilizados
*/
public static void main(String[] args) {
String
strHello = new
String("Hello");
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
}
// a continuacin se presenta lo que debe escribirse
// imprime: The strings are equivalent.
if (strHello.equals(strWorld)) {
stdOut.println("The strings are equivalent.");
}
// existe un grupo de mtodos estadsticos para convertir de
// un primitivo a una representacin String del mismo
String strValues;
strValues = String.valueOf(5.87); // strValues es ahora "5.87"
strValues = String.valueOf(true); // strValues es ahora "true"
strValues = String.valueOf(18); // strValues es ahora "18"
// concatenacin
stdOut.println(5.87 + "" + true + "" + 18);
// imprime 5.87true18
}
}
La Clase java.util.StringTokenizer
Tokenizacin (tokenizing) es el proceso de descomponer una cadena en piezas ms
pequeas llamadas tokens. Los tokens estn separados, o delimitados, por un carcter o un
grupo de caracteres. Por ejemplo, si consideramos que la siguiente cadena es tokenizada
utilizando espacios en blanco como delimitador, el resultado sera cinco tokens:
Cualquier carcter puede usarse como delimitador. Por ejemplo, si la cadena "Esta
cadena tiene cinco tokens" es tokenizada utilizando el carcter "n" como
delimitador, el resultado ser cinco tokens:
"Esta cade"
"a tie"
"e ci"
"co toke"
"s"
Sin embargo, los delimitadores tales como "n", son poco comunes.
La clase StringTokenizer es parte del paquete java.util. La siguiente, es una lista de
algunos de los mtodos de la clase StringTokenizer:
StringTokenizer(String str).
tokens.
boolean hasMoreTokens().
int countTokens().
La siguiente aplicacin almacena los datos del inventario de un producto (nombre, cantidad
y precio) en un String. El String est delimitado por el carcter de guin bajo ( _ ). La
aplicacin utiliza un objeto StringTokenizer para extraer los tokens del String.
1: import java.util.*;
2:
3: public class ProductInfo {
4:
5:
public static void main(String[]
6:
args) {
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19: }
Listado 1 ProductInfo.java
Cuando la aplicacin es ejecutada, los datos del inventario son desplegados.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
El archivo StringTokenizerClassDemo.java
import
import
/**
* Esta clase es una demostracin de la clase StringTokenizer
*
* @author
* version 1.0.0
*/
public class StringTokenizerClassDemo {
private static
PrintWriter
stdOut = new
PrintWriter(System.out, true);
/**
* Mtodo principal, muestra el uso de la clase StringTokenizer
*
* @param args no utilizado
*/
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
String
main(String[]
args)
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
" + str);
i = 1;
while (tokenizer.hasMoreTokens()) {
stdOut.println("Token #" + i + ": " + tokenizer.nextToken());
++i;
}
stdOut.println();
java.lang.Byte
java.lang.Short
java.lang.Integer
java.lang.Long
java.lang.Character
java.lang.Float
java.lang.Double
java.lang.Boolean
Observe que los nombres de las clases de envoltura son muy similares a los nombres de sus
contrapartes primitivos. Una clase de envoltura contiene un campo simple cuyo tipo es el
primitivo correspondiente. Por ejemplo, la clase Integer contiene un campo de tipo int.
La siguiente aplicacin ilustra el uso de la clase de envoltura Integer.
1: public class WrapperConversion {
2:
3:
public static void main(String[] args) {
4:
5:
Integer objectValue = new Integer(100);
6:
7:
int intValue = objectValue.intValue();
8:
long longValue = objectValue.longValue();
9:
double doubleValue = objectValue.doubleValue();
10:
String stringValue = objectValue.toString();
11:
12:
System.out.println("objectValue: " + objectValue);
13:
System.out.println("intValue: " + intValue);
14:
System.out.println("longValue: " + longValue);
15:
System.out.println("doubleValue: " + doubleValue);
16:
System.out.println("stringValue: " + stringValue);
17:
}
18: }
Listado 2 WrapperConversion.java
Las clases de envoltura son parte del paquete java.lang y por lo tanto no necesita ser
importado explcitamente. La aplicacin crea un objeto de envoltura para almacenar un
entero y despus encuentra los valores long, double y String equivalentes. La siguiente
figura muestra el resultado de la ejecucin de WrapperConversion:
Listado 3 ProductValue.java
La siguiente figura muestra el resultado de la ejecucin de ProductValue:
El Paquete java.io
Leyendo Valores Primitivos
El Paquete java.io
El paquete java.io tiene una gran cantidad de clases. Sin embargo, aqu slo estudiaremos
dos de ellas. La clase java.io.BufferedReader se utiliza para entrada. La clase
java.io.PrintWriter se utiliza para salida.
La siguiente es una plantilla para las clases que utilizan la consola E/S (entrada/salida):
1: import java.io.*; // contains BufferedReader and PrintWriter
2:
3: public class AnyClassUsingIO {
4:
5:
private static BufferedReader stdIn =
6:
new BufferedReader(new InputStreamReader(System.in));
7:
8:
private static PrintWriter stdOut =
9:
new PrintWriter(System.out, true);
10:
11:
private static PrintWriter stdErr =
12:
new PrintWriter(System.err, true);
13:
14:
/* other variables */
15:
16:
/*
methods
*/
17: }
System.out
System.err
1: import java.io.*;
2:
3: public class PrintlnDemo {
4:
5:
private static BufferedReader stdIn =
6:
new BufferedReader(new InputStreamReader(System.in));
7:
8:
private static PrintWriter stdOut =
9:
new PrintWriter(System.out, true);
10:
11:
private static PrintWriter stdErr =
12:
new PrintWriter(System.err, true);
13:
14:
public static void main(String[] args) {
15:
16:
stdOut.println("A line of output.");
17:
stdOut.println(5);
18:
stdOut.println(7.27);
19:
stdOut.println(true);
20:
21:
stdOut.println();
22:
}
23: }
Listado 2 PrintlnDemo.java
A continuacin se muestra la salida de PrintlnDemo:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23: }
main(String[]
args)
Listado 3 PrintDemo.java
A continuacin se presenta la salida de PrintDemo:
" + 5);
para vaciar el bfer despus de una llamada al mtodo print. El siguiente ejemplo ilustra
el uso del mtodo flush:
1: import java.io.*;
2:
3: public class Hello {
4:
5:
private static BufferedReader stdIn =
6:
new BufferedReader(new InputStreamReader(System.in));
7:
8:
private static PrintWriter stdOut =
9:
new PrintWriter(System.out, true);
10:
11:
private static PrintWriter stdErr =
12:
new PrintWriter(System.err, true);
13:
14:
public static void main(String[] args) throws IOException {
15:
16:
stdErr.print("Please enter you name on this line: ");
17:
stdErr.flush();
18:
19:
String input = stdIn.readLine();
20:
21:
stdOut.println("Hello " + input);
22:
}
23: }
Listado 4 Hello.java
La excepcin IOException ser estudiada en la pgina Objetos Excepcin. Observa que
stdErr, el flujo de salida estndar, se utiliza para desplegar mensajes. Si la llamada al
mtodo print que genera la salida del mensaje no es seguido por una llamada al mtodo
flush, el usuario probablemente no ver el mensaje adecuadamente. Usualmente, esto no
es deseable.
Para manejar las entradas, System.in puede usarse por s solo, pero sus capacidades son
limitadas ya que nicamente puede leer un carcter a la vez. Esto resultara fastidioso
cuando queremos leer toda una lnea de entrada. Encerrando System.in en un objeto
BufferedReader posibilita la lectura de lneas completas de entrada. El mtodo
BufferedReader empleado para este fin es readLine.
Una llamada al mtodo readLine ocasiona que el programa se detenga o que se bloquee
hasta que el usuario escriba una lnea de informacin. Cuando el usuario presiona la tecla
ENTER, la lnea es leda por el mtodo readLine y se regresa como String.
A continuacin se presenta la salida de Hello:
value = Integer.parseInt(stdIn.readLine());
17:
stdErr.print("Enter three integers on one line: ");
18:
stdErr.flush();
19:
20:
StringTokenizer tokenizer =
21:
new StringTokenizer(stdIn.readLine());
22:
23:
if (tokenizer.countTokens() != 3) {
24:
stdErr.println("Invalid input");
25:
} else {
26:
27:
int firstValue = Integer.parseInt(tokenizer.nextToken());
28:
int secondValue =
29: Integer.parseInt(tokenizer.nextToken());
30:
int thirdValue = Integer.parseInt(tokenizer.nextToken());
31:
32:
stdOut.println("First value: " + firstValue);
33:
stdOut.println("Second value: " + secondValue);
34:
stdOut.println("Third value: " + thirdValue);
35:
}
36:
}
}
Listado 5 ReadThreeIntegers.java
A continuacin se presenta la salida de ReadThreeIntegers:
Manejo de Excepciones
Objetos Excepcin
Clases de Excepciones
Excepciones Definidas por el Usuario
El Bloque try-catch
La Clusula throws
La Instruccin throw
Documentando Excepciones con Javadoc
Lecturas:
Requeridas:
o Barker, primera edicin, captulo 13 (pginas 3202).
o Barker, segunda edicin, captulo 13 (pginas 473
501).
Secuencia: Leer el libro de texto antes de leer esta pgina.
Manejo de Excepciones
Un cdigo robusto es un cdigo que responde apropiadamente a entradas invlidas y
condiciones ambientales inesperadas. Durante la ejecucin de un programa pueden ocurrir
muchas fallas o eventos excepcionales que interrumpen el flujo normal de un
programa. Por ejemplo, un programa puede tratar de abrir un archivo que no existe o dividir
un nmero entre cero. Un cdigo robusto maneja adecuadamente las fallas: contina la
ejecucin a pesar del problema o termina la ejecucin despus de desplegar un mensaje de
error.
En la programacin tradicional, debes incluir instrucciones condicionales para detectar y
manejar fallas en los programas. Frecuentemente, este cdigo es difcil de leer y mantener.
Por ejemplo, el siguiente es el pseudocdigo de un mtodo que lee un entero a partir de la
entrada estndar.
int readInteger () {
Lee una cadena de la entrada estndar
Convierte la cadena en un valor entero
Regresa el valor entero
}
Para hacer que tu mtodo sea robusto, debes aadir cdigo para detectar y manejar las fallas
potenciales:
int readInteger () {
while (true) {
lee una cadena de la entrada estndar;
if (la lectura de la entrada estndar falla) {
maneja el error de la entrada estndar;
} else {
convierte la cadena en un valor entero;
if (la cadena no contiene un entero) {
maneja el error de formato de nmero invlido;
} else {
regresa el valor entero;
}
}
}
}
El manejo de excepciones es un mecanismo que permite que las fallas sean manejadas fuera
del flujo normal del cdigo. El cdigo resultante es claro, fcil de leer y fcil de mantener.
El siguiente es un pseudocdigo que utiliza manejo de excepciones:
int readInteger () {
while (true) {
try {
lee una cadena a partir de la entrada estndar;
convierte la cadena en un valor entero;
regresa el valor entero;
} catch (la lectura de la entrada estndar fall) {
maneja el error de entrada estndar;
} catch (la cadena no contiene un entero) {
maneja el error de formato de nmero invlido;
}
}
}
Objetos Excepcin
En Java, una excepcin es un objeto que describe una situacin anormal. Un objeto
excepcin (exception object) contiene la siguiente informacin:
El tipo de excepcin
Una pila de llamadas (call stack) que indica donde ocurri la excepcin
Cuando ocurre una situacin anormal, un mtodo puede crear un objeto excepcin y
despus lanzarlo (throw). Si el mtodo que hace la llamada no est preparado para atrapar
(catch) el objeto excepcin, ste lanza el objeto excepcin al mtodo que lo llama y as
sucesivamente. El objeto excepcin pasa a travs de la secuencia de mtodos que han sido
llamados (la pila de llamadas) hasta que es atrapado. El mtodo que atrapa el objeto
excepcin utiliza la informacin que se encuentra en el objeto para manejar la excepcin.
Cuando un mtodo lanza una excepcin, ninguna de las instrucciones restantes en dicho
mtodo son ejecutadas. Si ninguno de los mtodos de la pila de llamadas atrapa la
excepcin y el mtodo que se encuentra en cima de la pila es main, el programa despliega,
en el flujo de error estndar, un mensaje que identifica la excepcin y finaliza. Para
prevenir la terminacin prematura de un programa, debes incluir bloques try-catch que
permitan que el programa se recupere de las fallas.
La siguiente figura ilustra cmo se lanzan y se atrapan las excepciones.
/**
* Esta clase demuestra cmo se lanzan y se atrapan excepciones.
*
* @author
* @version 1.0.0
*/
public class ExceptionDemo {
/**
* Llama a methodA
*
* @param args no utilizado
*/
public static void main(String[] args)
methodA();
System.out.println("MethodA passed");
}
/**
* Llama a
el
* error y termina el programa.
*/
public static void methodA() {
try {
methodB();
System.out.println("MethodB passed");
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
/**
* Llama a methodC. Si ocurre una excepcin, la lanza al mtodo
que
* hizo la llamada.
*
* @throws Exception cuando methodC es llamado.
*/
public static void methodB() throws Exception {
methodC();
System.out.println("MethodC passed");
}
/**
* Llama a methodD. Si ocurre una excepcin, la lanza al mtodo
que
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
* hizo la llamada.
*
* @throws Exception cuando ethodD es llamado.
*/
public static void methodC() throws Exception
methodD();
System.out.println("MethodD passed");
}
/**
* Lanza una excepcin
*
* @throws Exception cada vez que methodD es llamado.
*/
public static void methodD() throws Exception {
throw new
}
}
Listado 1 ExceptionDemo.java
En la clase ExceptionDemo, el mtodo main llama a methodA, methodA llama a methodB,
methodB llama a methodC y methodC llama a methodD. El ltimo mtodo de la secuencia,
methodD, crea un nuevo objeto de excepcin y lo lanza al methodC. La excepcin pasa por
methodC y methodB hasta que es atrapado por methodA. methodA maneja la excepcin
imprimiendo un rastro de la pila y terminando el programa. El rastro de la pila muestra la
secuencia de mtodos que fueron llamados antes de que la excepcin fuera lanzada. La
siguiente figura muestra la consola de salida al ejecutar ExceptionDemo:
Observa que las instrucciones de imprimir que se encuentran en methodB y methodC nunca
fueron ejecutadas.
Los objetos excepcin cuentan con un grupo de mtodos comunes. Incluyen:
String getMessage(). Obtiene el argumento que fue pasado al constructor del objeto
de excepcin.
String toString(). El nombre de la excepcin (su tipo), seguido por dos puntos ( : ),
seguidos por el String regresado por el mtodo getMessage.
Clases de Excepciones
Los objetos excepcin son instancias de clases que descienden de la clase Throwable.
Throwable tiene dos subclases: Error y Exception.
La clase Error es utilizada para problemas serios, donde es poco probable que una
aplicacin se recupere. Un ejemplo es el error "out of memory" (sin memoria).
La clase Exception es utilizada para las condiciones anormales que una aplicacin
puede esperar que sean manejadas.
Java divide las excepciones en dos categoras: las excepciones verificadas (checked
exceptions) y las excepciones no verificadas (unchecked exceptions). Las excepciones que
no son "verificadas" por el compilador son llamadas excepciones no verificadas; las
excepciones que son "verificadas" por el compilador, son llamadas excepciones verificadas.
El compilador no compilar un archivo si contiene un mtodo donde pueda ocurrir una
excepcin verificada y el mtodo no maneje la excepcin verificada en un bloque catch o
lo enliste en el encabezado del mtodo. Las clases RuntimeException, Error y sus
subclases son excepciones no verificadas. Todas las dems clases de excepcin son
excepciones verificadas.
/**
* Lanzada cuando ocurre un error fuera de rango.
*
* @author nombre del autor
* @version 1.0.0
*/
public class OutOfRangeException extends Exception
/**
* Construye una nueva instancia de
<code>OutOfRangeException</code>.
*/
public OutOfRangeException() {
}
/**
* Construye una nueva instancia de
<code>OutOfRangeException</code>
* que incluye una explicacin.
*
* @param message Informacin adicional sobre esta excepcin.
*
Puede ser nulo.
*/
public OutOfRangeException(String message) {
super(message);
}
}
Listado 2 OutOfRangeException.java
El Bloque try-catch
Si un mtodo elige manejar una excepcin, debe tener un bloque try-catch. Un bloque
try delimita el cdigo que puede lanzar una excepcin. Un bloque try tiene el siguiente
aspecto:
try
{
// cdigo que puede lanzar excepciones
A un bloque try le siguen uno o ms bloques catch. Un bloque catch tiene el siguiente
aspecto:
catch (TipoExcepcin
e)
Pueden aparecer muchos bloques catch despus de un bloque try, cada uno atrapando una
excepcin diferente. Cuando se lanza una excepcin, cada bloque catch es examinado,
comenzando con el bloque catch que se encuentra inmediatamente despus del bloque
try. El tipo de la excepcin lanzada es comparado con el tipo del argumento del bloque
catch. Cuando encuentra una coincidencia, es ejecutado el cuerpo del bloque catch que
coincide. Entonces, la ejecucin sigue despus del ltimo bloque catch. Si ningn bloque
catch coincide, la excepcin se deja pasar a la pila de llamadas.
Considera el siguiente cdigo. La clase IntegerReader tiene un mtodo llamado
readInteger que lee un entero de la entrada estndar:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
import java.io.*;
/**
* Esta clase provee un mtodo que lee un entero de la
* entrada estndar.
*
* @author
* @version 1.0.0
*/
public class IntegerReader {
private static BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
private static PrintWriter
stdErr =
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55: }
{
try
{
stdErr.print("Enter an integer >
stdErr.flush();
");
return Integer.parseInt(stdIn.readLine());
} catch (IOException ioe)
ioe.printStackTrace();
System.exit(1);
// Termina el programa
Listado 3 IntegerReader.java
El mtodo BufferedReader.readLine que se encuentra en la lnea 43 puede lanzar una
excepcin de tipo IOException. El bloque catch de la lnea 45 maneja la excepcin
IOException desplegando, en el flujo de error estndar, la pila de llamadas y terminando el
programa. El mtodo Integer.parseInt de la lnea 43 puede lanzar una excepcin de tipo
NumberFormatException. El bloque catch de la lnea 50 maneja la excepcin
NumberFormatException desplegando, en el flujo de error estndar, el mensaje "Invalid
number format" y la ejecucin contina; es decir, se le da otra oportunidad al usuario de
introducir un entero.
El argumento de un bloque catch puede ser engaoso. Por ejemplo, el siguiente bloque
atrapar una excepcin IOException; tambin atrapar una excepcin
catch
FileNotFoundException
FileNotFoundException
una
porque
las
clases
y EOFException son subclases de la clase IOException. Ver
EOFException
Figura 3.
catch (IOException
e)
La Clusula throws
Si una excepcin verificada puede ocurrir en un mtodo y dicho mtodo no tiene un bloque
catch para manejar la excepcin verificada, entonces sta debe ser declarada en el
encabezado del mtodo utilizando una clusula throws. Por ejemplo, si puede ocurrir una
excepcin de tipo IOException en un mtodo readInteger y readInteger no lo maneja,
entonces readInteger debe tener el siguiente encabezado:
public int readInteger() throws IOException {
}
import java.io.*;
/**
* Esta clase provee un mtodo que lee un entero de la
* entrada estndar.
*
* @author
* @version 1.0.0
*/
public class IntegerReaderThrowsException {
private static BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
private static PrintWriter stdErr =
new PrintWriter(System.err, true);
18:
private static PrintWriter stdOut =
19:
new PrintWriter(System.err, true);
20:
21:
/**
22:
* Prueba el mtodo <code>readInteger</code>
23:
*
24:
* @param args no utilizado
25:
* @throws IOException si hay error al leer de la entrada
26: estndar.
27:
*/
28:
public static void main (String[] args) throws IOException {
29:
30:
stdOut.println("The value is: " + readInteger());
31:
}
32:
33:
/**
34:
* Lee un entero de la entrada estndar.
35:
*
36:
* @return regresa el valor <code>int</code>.
37:
* @throws IOException si hay error al leer de la entrada
38: estndar.
39:
*/
40:
public static int readInteger() throws IOException {
41:
42:
do {
43:
try {
44:
stdErr.print("Enter an integer> ");
45:
stdErr.flush();
46:
47:
return Integer.parseInt(stdIn.readLine());
48:
49:
} catch (NumberFormatException nfe) {
50:
stdErr.println("Invalid number format");
51:
}
52:
} while (true);
}
}
Listado 4 IntegerReaderThrowsException.java
La Instruccin throw
Los mtodos definidos por el usuario tambin pueden lanzar excepciones. Para lanzar una
excepcin, utilizan la palabra clave throw, seguida por un objeto excepcin. Por ejemplo:
throw
new
OutOfRangeException();
El objeto excepcin es creado como cualquier otro objeto, utilizando el operador new y un
constructor. La siguiente sentencia utiliza el constructor de la excepcin
OutOfRangeException que acepta un argumento de tipo String.
throw
new
import java.io.*;
/**
* Envuelve un valor entero positivo.
*
* @author
* @version 1.0.0
*/
public class PositiveInteger {
private static BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
private static PrintWriter stdErr =
new PrintWriter(System.err, true);
private static PrintWriter stdOut =
new PrintWriter(System.err, true);
private int value;
/**
* Prueba el mtodo <code>readInteger</code>
*
* @param args no utilizado
* @throws IOException si hay error al leer de la entrada
estndar.
*/
public static void main(String[] args) throws IOException
PositiveInteger object;
do
{
try
{
stdErr.print("Enter an integer> ");
stdErr.flush();
int value = Integer.parseInt(stdIn.readLine());
object = new PositiveInteger(value);
break;
54:
* Construye un objeto <code>PositiveInteger</code> con el
55:
* valor especificado por el argumento.
56:
*
57:
* @param initialValue un entero. El valor debe ser positivo.
58:
* @throws OutOfRangeException si el valor es negativo.
59:
*/
60:
private PositiveInteger(int initialValue) throws
61: OutOfRangeException {
62:
63:
if (initialValue < 0) {
64:
65:
throw new OutOfRangeException("Number not positive");
66:
67:
} else {
68:
this.value = initialValue;
69:
}
70:
}
71:
72:
/**
73:
* Regresa el nmero positivo
74:
*
75:
* @return regresa el valor
76:
*/
77:
public int getValue() {
78:
79:
return this.value;
80:
}
81:
82:
/**
83:
* Modifica el nmero positivo.
84:
*
85:
* @param newValue el nuevo entero. El valor debe ser positivo.
86:
* @throws OutOfRangeException si el nuevo valor es negativo.
87:
*/
88:
private void setValue (int newValue) throws OutOfRangeException {
89:
90:
if (newValue < 0) {
91:
92:
throw new OutOfRangeException("Number not positive");
93:
94:
} else {
95:
this.value = newValue;
96:
}
}
}
Listado 5 PositiveInteger.java
En esta clase, tanto el constructor como el mtodo setValue crean y lanzan una excepcin
de tipo OutOfRangeException cuando el valor del argumento no es positivo (lneas 59 y
86). Observa que la excepcin OutOfRangeException es atrapada en el mtodo main que
se encuentra en la lnea 44.
La etiqueta Javadoc para una excepcin es la etiqueta @throws tambin puede emplearse
la etiqueta @exception. El comentario Javadoc para un mtodo debe tener una etiqueta
@throws por cada excepcin verificada que el mtodo pudiera lanzar. Tambin puede tener
etiquetas @throws para las excepciones no verificadas, pero no es necesario. El comentario
Javadoc no debe tener una etiqueta @throws para las excepciones atrapadas y manejadas
por el mtodo. Utiliza los siguientes lineamientos para documentar excepciones:
Requerida:
o Software de Java, Sun Microsystems, Inc, Code
Conventions for the Java Programming Language
(Convenciones de Cdigo para el Lenguaje de
Programacin Java). Este documento contiene las
convenciones estndar que Sun Microsystems sigue y
recomienda a los dems. Cubre nombres de archivos,
organizacin de archivos, sangrado del cdigo,
comentarios, declaraciones, instrucciones, espacios
en blanco, convenciones de nombres y prcticas de
programacin. Tambin incluye un ejemplo de
cdigo.
Uno de los objetivos de este curso es que aprendas a utilizar un buen estilo de
programacin. Un buen estilo de programacin es un componente importante de la prctica
profesional de desarrollo de software.
Tu cdigo existir por un tiempo largo. Debes asegurarte que tu cdigo sea legible y
fcil de entender para los dems. Un cdigo difcil de entender podra ser descartado
y reescrito.
Las convenciones de cdigo deben asegurar que la estructura lgica del cdigo es
fcil de seguir. Por ejemplo, las instrucciones en el cuerpo de un bucle deben
sangrarse un nivel.
1.1.7 Javadoc
Lecturas:
Requeridas:
o Java Software, Sun Microsystems, Inc., How to Write Doc
Comments for the Javadoc Tool (Cmo Escribir
Comentarios Doc para la Herramienta Javadoc). Este
documento describe las convenciones utilizadas para
escribir comentarios Javadoc en Sun.
Sintaxis de Javadoc
Los comentarios en Javadoc inician con la secuencia "diagonal-asterisco-asterisco" (/**) y
cierran con una secuencia "asterisco-diagonal" (*/), ya sea en una o ms lneas. Cuando
estos delimitadores se extienden a ms de una lnea, cada lnea interna comienza con un
solo asterisco ( * ), sangrado de tal manera que est alineado con el primer asterisco que
inici el comentario. La secuencia de cierre tambin debe alinearse con el primer asterisco
de la secuencia de apertura. El texto del comentario comienza un espacio despus del
asterisco que comienza la lnea. La estructura de varias lneas se muestra enseguida:
/**
* body text
* body text
* body text
*/
constructores
6. @see referencia a una entidad relacionada; utilizada para clases, constructores, mtodos
y campos de datos
/**
* <p>Esta clase almacena el valor de dos enteros.</p>
* <p>Esta clase es escrita con el propsito de hacer una demostracin
de los
* comentarios Javadoc. Los comentarios Javadoc para las clases,
pueden ser
* separados en dos partes: una parte de descripcin y una parte de
etiquetas.
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
first;
second;
/**
* Inicializa ambos enteros en <code>0</code>.
*/
public TwoInts() {
this.first = 0;
this.second = 0;
}
/**
* Inicializa ambos enteros con los argumentos.
*
* @param initialFirst valor al cual es inicializado el campo
*
<code>first</code>
* @param initialSecond valor al cual es inicializado el campo
*
<code>second</code>
*/
public TwoInts(int initialFirst, int initialSecond) {
this.first = initialFirst;
this.second = initialSecond;
}
/**
* Calcula la suma de dos enteros.
*
* @return regresa la suma de dos enteros
*/
public int sum() {
return
this.first + this.second;
}
/**
* Incrementa el campo <code>first</code> por el argumento.
*
* @param value el valor por el cual se incrementar el campo
*
<code>first</code>
*/
public void addToFirst(int value) {
this.first += value;
57:
58: }
59:
60:
61:
62:
63:
Listado 1 TwoInts.java
Una vez que los comentarios Javadoc estn completos, emplea el comando javadoc para
generar la documentacin del programa. La siguiente figura ilustra la sintaxis del comando
javadoc:
Esto generar una coleccin de pginas HTML que sern la documentacin de la clase
TwoInts. Esta coleccin puede visualizarse en un navegador Web. Abre el archivo
index.html que se encuentra en el directorio que almacena el archivo fuente TwoInts.
Este curso solamente requiere comentarios Javadoc para las entidades public y protected
clases, constructores, mtodos y variables precedidas por las palabras clave public o
protected.
1.1.8 Depurando
El Proceso de Depuracin
Instrucciones de Imprimir
El Depurador
El Proceso de Depuracin
Depuracin (debugging) es el proceso de identificar un error y corregirlo. Una depuracin
efectiva no se realiza de manera natural. Para muchos desarrolladores, la depuracin
consume muchas horas. El tiempo necesario para encontrar un error y corregirlo depender
de tu competencia en depuracin. El uso de estrategias ad hoc, como tratar de adivinar por
ejemplo, puede hacer que desperdicies grandes cantidades de tiempo sin obtener ningn
resultado. El proceso de identificar un error debe ser metdico y no debe comenzar hasta
que el desarrollador ha entendido bien el cdigo del programa. En esta pgina,
describiremos una tcnica de depuracin y presentaremos algunas herramientas para
depuracin. En la pgina Depurando con Eclipse, utilizaremos la tcnica descrita aqu para
depurar un programa.
La siguiente figura muestra un resumen de una efectiva tcnica para depurar un programa:
1. Crea un caso de prueba: para diagnosticar y corregir un error, debes ser capaz de
reproducirlo. Para ahorrar tiempo en las pruebas, crea un caso de prueba pequeo
que reproduzca el error. Implementa este caso de prueba en una clase separada o en
el mtodo main del programa que ser depurado.
2. Ubica el cdigo que causa el error. Un buen lugar para comenzar la bsqueda es el
caso de prueba mismo: encuentra la lnea de cdigo en el caso de prueba donde
aparece el error. Esta lnea te dirigir al cdigo que contiene el error. Una vez que
hayas ubicado el cdigo, estudia sus estructuras de control y sus variables.
Determina cmo se espera que se comporte el cdigo y qu valores se espera que
contengan las variables.
3. Repasa el cdigo lnea por lnea. Presta particular atencin a las instrucciones que
asignen un nuevo valor a una variable relevante. Identifica el cdigo que causa el
error.
4. No asumas que el error es causado por un problema de lgica en esta parte del
cdigo. Puede ser causado por datos errneos originados en otras reas del cdigo.
Si es as, localiza el cdigo donde se originaron los datos errneos y repite la
operacin a partir del paso 2.
5. Repara el cdigo:
o La correccin no debe "esconder", "maquillar" o "reprimir" el error.
o La correccin no debe introducir nuevos errores. El desarrollador debe
entender cmo la correccin afecta otras partes del cdigo porque una
correccin puede tener efectos colaterales inesperados.
o Resulta prudente revisar el cdigo circundante. En muchos casos, hay ms
de un error en la misma parte del cdigo.
Instrucciones de Imprimir
El uso de instrucciones de imprimir es una tcnica comn. Est disponible en muchos
idiomas y es fcil de implementar. Las instrucciones de imprimir se utilizan para desplegar
informacin importante mientras se ejecuta el cdigo. La informacin puede incluir:
sus argumentos. La segunda instruccin de imprimir despliega los valores de las variables
locales.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
import java.io.*;
/**
* Esta aplicacin despliega la suma de enteros en el rango
* especificado.
*
* @author
* @version 1.0.0
*/
public class SumCalculator {
private static BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
private static PrintWriter stdOut =
new PrintWriter(System.out, true);
private static PrintWriter stdErr =
new PrintWriter(System.err, true);
/**
* Regresa la suma de enteros en el rango
* especificado [inferior,superior].
*
* @param lower el lmite inferior.
* @param upper el lmite superior.
* @return regresa la suma de enteros en el rango
*
especificado [inferior,superior].
*/
public static int sumRange(int lower, int upper) {
stdErr.println(" sumRange called. lower:" + lower
+ " upper:" + upper);
int
total = 0;
total:"
return total;
}
/**
* Despliega la suma de enteros en el rango especificado.
*
* @param args no usado.
*/
public static void main(String[] args) {
int lower;
54:
int upper;
55:
56:
try {
57:
stdErr.print("lower limit: ");
58:
stdErr.flush();
59:
lower = Integer.parseInt(stdIn.readLine());
60:
stdErr.print("upper limit: ");
61:
stdErr.flush();
62:
upper = Integer.parseInt(stdIn.readLine());
63:
stdOut.println("The result is: " + sumRange(lower,
64: upper));
65:
} catch (NumberFormatException nfe) {
66:
stdErr.println(nfe);
67:
} catch (IOException ioe) {
68:
stdErr.println(ioe);
69:
}
70:
71:
}
}
Listado 1 SumCalculator
Cuando la aplicacin es ejecutada, despliega el nombre del mtodo, los argumentos del
mtodo y los valores de la variable de control del bucle y de la variable local total en cada
iteracin del bucle. Toma en cuenta que este cdigo no tiene ningn error. Slo estamos
demostrando cmo pueden ser utilizadas las instrucciones de imprimir para rastrear la
ejecucin de un programa.
El Depurador
Un depurador (debugger) es una herramienta conveniente para localizar la fuente de los
errores. Un depurador te permite ejecutar una lnea a la vez y observar su efecto en las
variables del programa. Existen muchos depuradores de Java disponibles:
Introduccin
El Ejemplo
Crear el Proyecto
Importar la Clase Employee
Ejecutar la Aplicacin
Mostrar los Nmeros de Lnea
Depurar la Clase
Colocar un Punto de Ruptura
Monitorear la Ejecucin
Diagnosticar y Corregir el Error
Introduccin
En esta seccin, realizaremos una demostracin del proceso de depuracin utilizando un
depurador. Utilizaremos el depurador incluido en Eclipse. Las funciones bsicas provistas
por este depurador son similares a las que ofrecen otros depuradores. Por lo tanto, tambin
puedes avanzar en este tutorial utilizando otro depurador.
El Ejemplo
La clase Employee representa a un empleado en un sistema de nminas. Los objetos de la
clase Employee contienen el nombre y el salario del empleado. El salario de un empleado
es una funcin del salario por hora, el nmero de horas trabajadas y las comisiones de
ventas. La informacin de cada empleado es almacenada en una cadena con el siguiente
formato:
name_hourlyWage_hoursWorked_sale1,sale2,...,salen
Donde,
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
import java.util.*;
/**
* Modela la informacin de un empleado.
*
* @author
* @version 1.0.0
*/
public class Employee {
private static PrintWriter stdErr =
new PrintWriter(System.err, true);
private final static double
SALE_COMMISSION = 0.02;
DATA_DELIM = "_";
SALES_DELIM = ",";
private String
name;
private double
earnings;
/**
* Caso de prueba para la clase <code>Employee</code>
*
* @param args no utilizado.
*/
public static void main(String[] args) {
String
Employee
try {
if (employee.getEarnings() == 222.0) {
stdErr.println("Test 1 passed");
} else {
stdErr.println("Test 1 failed");
}
} catch (NumberFormatException iae) {
stdErr.println("Test 1 failed, " + iae);
}
data = "John Smith_10.00_20_1000.0,100.0";
employee = new Employee(data);
try {
if (employee.getEarnings() == 222.0) {
stdErr.println("Test 2 passed");
} else {
stdErr.println("Test 2 failed");
}
} catch (NumberFormatException iae) {
stdErr.println("Test 2 failed, " + iae);
}
59:
}
60:
61:
/**
62:
* Construye un objeto <code>Employee</code> con la
63:
* informacin especificada en el parmetro <code>data</code>.
64:
* <p>
65:
* Los datos de entrada tienen el siguiente formato:
66:
* </p>
67:
* <p>
68:
* nombre_salarioHora_horasTrabajadas_venta1,venta2,...,ventan
69:
* </p>
70:
* <p>
71:
* Los campos de venta almacenan la cantidad de cada venta
72: realizada por el
73:
* empleado.
74:
* </p>
75:
*
76:
* @param data una cadena con la informacin del empleado.
77:
* @throws NumberFormatException si los datos contienen nmeros
78:
*
invlidos
79:
*/
80:
public Employee(String data) throws NumberFormatException {
81:
82:
StringTokenizer tokenizer =
83:
new StringTokenizer(data, DATA_DELIM);
84:
85:
try {
86:
this.name = tokenizer.nextToken();
87:
88:
double hourlyWage =
89:
Double.parseDouble(tokenizer.nextToken());
90:
int hoursWorked =
91:
Integer.parseInt(tokenizer.nextToken());
92:
93:
double commission = (tokenizer.hasMoreTokens()) ?
94:
95: computeCommission(tokenizer.nextToken()) : 0;
96:
97:
this.earnings = hourlyWage * hoursWorked + commission;
98:
99:
} catch (NumberFormatException nfe) {
100:
throw new NumberFormatException(
101:
"bad employee data: " + data);
102:
}
103:
}
104:
105:
/**
106:
* Obtiene el nombre del empleado.
107:
*
108:
* @return regresa una cadena con el nombre del empleado.
109:
*/
110:
public String getName() {
111:
112:
return this.name;
113:
}
114:
115:
/**
116:
* Obtiene los ingresos del empleado.
117:
*
118:
* @return los ingresos del empleado.
119:
*/
120:
public double getEarnings() {
121:
122:
return this.earnings;
123:
}
124:
125:
/*
126:
* Calcula la comisin del empleado con los datos
127:
* especificados en el parmetro.
128:
*
129:
* @param data una cadena con los datos de las ventas del
130: empleado.
131:
* @return regresa la comisin ganada por el empleado.
132:
* @throws NumberFormatException si los datos contienen nmeros
133:
*
invlidos
134:
*/
135:
private double computeCommission(String data)
136:
throws NumberFormatException {
137:
138:
StringTokenizer tokenizer =
139:
new StringTokenizer(data, SALES_DELIM);
140:
141:
double total = 0.0;
142:
143:
try {
144:
145:
String token = tokenizer.nextToken();
146:
147:
while (tokenizer.hasMoreTokens()) {
148:
token = tokenizer.nextToken();
149:
total += Double.parseDouble(token);
150:
}
151:
152:
} catch (NumberFormatException nfe) {
153:
throw new NumberFormatException(
154:
"bad sales data: " + data);
155:
}
156:
return total * SALE_COMMISSION;
}
}
Listado 1 Employee.java
En la lnea 92, el operador condicional ( ? : ) utiliza el valor booleano de una expresin
para decidir cul de dos otras expresiones debe ser evaluada. La siguiente asignacin:
variable = condicin ? expresin1 : expresin2;
variable = expresin1;
} else {
variable = expresin2;
}
Crear el Proyecto
El primer paso es crear el proyecto de Java.
1. Abre Eclipse y despus abre la perspectiva de Java.
2. En el men File (archivo), apunta a New (nuevo) y despus selecciona Project
(proyecto).
3. En el asistente de New Project, selecciona Java en el panel izquierdo, da un clic en
Java Project (proyecto de Java) en el panel derecho y despus elige Next
(siguiente).
Ejecutar la Aplicacin
1. Presiona la flecha que se encuentra a la derecha del botn Run en la barra de
herramientas, apunta a Run As y selecciona Java Application.
Depurar la Clase
1. Para depurar la clase, presiona la flecha que se encuentra a la derecha del botn
Debug (depurar) en la barra de herramientas. Apunta a Debug As y despus
selecciona Java Application.
Un buen punto para comenzar es la lnea que reporta el error. (Ver la tcnica de depuracin
descrita en la pgina Depurando.) En este ejemplo, la lnea 40 del mtodo main reporta el
error.
1. En el editor, ve a la lnea 40. Da un clic derecho al nmero de lnea y selecciona
Add Breakpoint (aadir punto de ruptura).
Monitorear la Ejecucin
resume
step
into
step
over.
step
return
terminate
Aborta la ejecucin.
Hemos descubierto que el valor del primer token no es aadido a la variable total. Un
error comn es disfrazar el error en vez de repararlo. Por ejemplo, podemos pensar que el
orden de las lnea 145 y 146 est incorrecto e intercambiarlas:
Introduccin
Notacin de Clase
Lecturas:
Requerida:
o Barker, primera edicin, captulo 10 (pginas 2303).
o Barker, segunda edicin, captulo 10 (pginas 372
6).
Introduccin
El Lenguaje de Modelacin Unificado (Unified Modeling Language o UML por sus siglas
en ingls) es un lenguaje grfico para modelar los aspectos estticos y dinmicos de un
sistema. UML es una unificacin de las metodologas desarrolladas por Grady Booch,
James Rumbaugh e Ivar Jacobsen. El Grupo de Administracin de Objetos (Object
Management Group u OMG), una organizacin sin fines de lucro que promueve el uso de
la tecnologa orientada a objetos, ha asumido la responsabilidad del futuro desarrollo del
estndar UML.
UML es un lenguaje que unifica las mejores prcticas de la ingeniera para modelar
sistemas. Define diferentes diagramas grficos que proveen mltiples perspectivas de un
sistema en desarrollo. UML define los siguientes diagramas:
Diagrama de clase
Diagramas de comportamiento:
o Diagrama de estado
o Diagrama de actividad
o Diagramas de interaccin:
Diagrama de secuencia
Diagrama de colaboracin
Diagramas de implementacin:
o Diagrama de componentes
o Diagrama de despliegue
A lo largo de este curso, utilizaremos diagramas de clase para discutir los diferentes
elementos del diseo orientado a objetos. Los diagramas de clase muestran la estructura
interna de las clases y sus relaciones con otros elementos del sistema.
Notacin de Clase
El elemento fundamental de un diagrama de clase es la notacin de una clase. Como se
muestra en la Figura 1, una clase est representada por un rectngulo con tres secciones. La
primera seccin contiene el nombre de la clase; la segunda seccin describe los atributos de
la clase y la tercera seccin describe los mtodos de la clase.
La visibilidad privada no permite que otras clases tengan acceso a este atributo o mtodo,
mientras que la visibilidad pblica permite que otras clases tengan acceso a este atributo o
mtodo.
Comnmente, los atributos se definen como privados; de esta manera el objeto puede
esconder su informacin para mantener el control de su estado. Un mtodo se define como
pblico si se espera que sea llamado por otras clases y se define como privado si no se
pretende que sea llamado por clases externas.
Cuando una clase necesita brindar acceso a sus atributos privados, la convencin indica
definir los mtodos pblicos para acceder el valor de un atributo o modificar un atributo.
Estos mtodos son conocidos como selectores (accessors) o modificadores (mutators),
respectivamente.
A continuacin se muestra la representacin UML de la clase Employee (empleado). Esta
clase contiene tres atributos privados: name (nombre), hourlyWage (salario por hora) y
hoursWorked (horas trabajadas). Tambin contiene los siguientes mtodos pblicos:
Asociaciones
Asociaciones de Una Va (One-Way) y Dos Vas (Two-Way)
Multiplicidad
Agregacin
Especializacin/Generalizacin
Lecturas:
Requeridas:
o Barker, first edition, chapter 5 (pages 113 20); chapter
10 (pages 233 40).
o Barker, second edition, chapter 5 (pages 16774);
chapter 10 (pages 37686).
Asociaciones
Una asociacin representa la relacin entre dos o ms clases. Una asociacin binaria es
una relacin entre dos clases. Existe una asociacin binaria si un objeto de una clase
requiere un objeto de otra clase para hacer su trabajo. En UML, una asociacin binaria est
representada por una lnea slida que conecta dos clases.
Por ejemplo, en un saln de clases, un profesor (Professor) ensea a los estudiantes
(Student). Esta asociacin est expresada en el siguiente diagrama de clase:
En un sistema bancario, los clientes (Client) tienen cuentas de banco (BankAccount). Esta
asociacin se encuentra expresada en el siguiente diagrama de clase:
Figura 3 Asociacin de una va entre las clases que representan carros y motores
Observa el atributo engine al final de la lnea. La clase Car tiene un atributo engine que
contiene una referencia a un objeto de la clase Engine.
El siguiente ejemplo muestra la relacin entre las clases Country (pas), Government
(gobierno) y Capital. Cada pas tiene un gobierno y una capital. Los atributos al final de
las lneas indican que la clase Country tiene una referencia a un objeto de la clase
Government as como una referencia a un objeto de la clase Capital:
Figura 4 Asociaciones de una va entre las clases que representan pases, gobiernos y capitales
Una clase puede contener una o ms asociaciones con otra clase. Por ejemplo, el siguiente
diagrama de clase muestra dos asociaciones entre las clases Flight (vuelo) y Pilot
(piloto), una asociacin con el atributo pilot (piloto) y otra con el atributo coPilot
(copiloto):
Multiplicidad
La multiplicidad indica el nmero de instancias de una clase que pueden ser asociadas a
una sola instancia de otra clase. Por ejemplo, un carro tiene cuatro llantas y un motor,
tambin un cliente tiene una o ms cuentas de banco. La multiplicidad puede especificarse
con un solo entero o como un rango n..m, donde n es el lmite inferior y m es el lmite
superior. Podemos utilizar un asterisco ( * ) para denotar que no existe un lmite superior. A
continuacin se presentan las multiplicidades ms comunes:
0..1
0..* *
Cero o ms instancias
1..*
Una o ms instancias
En una asociacin uno a uno, exactamente una instancia de cada clase est relacionada
solamente con una instancia de otra clase. Por ejemplo, la asociacin entre las clases Car
(carro) y Engine (motor) puede definirse como una asociacin uno a uno, indicando que
cada carro contiene solo un motor y que cada motor est instalado solamente en un carro:
El siguiente diagrama de clase muestra las asociaciones uno a uno entre las clases Country
(pas), Government (gobierno) y Capital. Cada pas contiene slo un gobierno y una
capital. Cada gobierno est asociado con un solo pas y cada capital est asociada con solo
un pas:
En una asociacin uno a muchos entre las clases A y B, una instancia de la clase A puede
estar relacionada con muchas instancias de la clase B, pero una instancia de la clase B est
relacionada solamente con una instancia de la clase A. Por ejemplo, en la asociacin entre
las clases Client (cliente) y BankAccount (cuenta bancaria), cada cliente puede tener
muchas cuentas de banco, pero cada cuenta de banco tiene solamente un propietario:
El siguiente diagrama muestra la relacin entre las clases que representan un calendario:
En este diagrama, un ao (Year) contiene doce meses (Month) y cada mes est asociado con
solo un ao. (Toma en cuenta que los meses Enero1962 y Enero2029 son instancias
diferentes de la clase Month.) De la misma forma, un mes contiene cuatro o cinco semanas
(Week) y cada semana est asociada con solo un mes. Finalmente, una semana contiene
siete das (Day) y cada da est asociado con una sola semana.
Asociacin muchos a muchos
En una asociacin muchos a muchos entre las clases A y B, una instancia de la clase A puede
estar relacionada con muchas instancias de la clase B y una instancia de la clase B puede
estar relacionada con muchas instancias de la clase A. Por ejemplo, en la asociacin entre
las clases Student (estudiante) y Course (curso), cada estudiante toma muchos cursos y
cada curso est siendo impartido para muchos estudiantes:
Agregacin
La agregacin es una forma especial de asociacin. Una agregacin es una asociacin entre
las clases A y B, donde cada instancia de la clase A contiene, o est compuesta por,
instancias de la clase B. En este sentido, una instancia de la clase B es parte de una instancia
de la clase A. A la instancia de la clase A se le conoce como agregada (aggregate) y a la
instancia de la clase B se le conoce como componente (component). Por ejemplo, un libro
(Book) est compuesto por una tabla de contenidos (TableOfContents), ningn o un
prefacio (Preface), uno o ms captulos (Chapter) y un ndice (Index). En un libro, cada
captulo est compuesto por una o ms secciones (Section) y cada seccin est compuesta
por uno o ms prrafos (Paragraph) y ninguna o algunas figuras (Figure).
Una relacin de agregacin se representa en UML mediante una lnea con un diamante
junto a la clase agregada:
Especializacin/Generalizacin
La Especializacin/Generalizacin representa a la relacin es un. Por ejemplo, una ballena
es un mamfero y un cliente es una persona. La especializacin/generalizacin permite que
la clase A sea definida como especializacin de otra clase B, ms general. La clase A es
llamada clase de especializacin (specialization class) y la clase B es llamada clase de
generalizacin (generalization class). La especializacin/generalizacin se representa en
UML mediante una lnea con un tringulo junto a la clase de generalizacin:
Figura 15 Relacin de especializacin/generalizacin entre clases que representan clientes, empleados y personas
En este ejemplo:
Una instancia de la clase JpgFile contiene los atributos especficos de la clase JpgFile,
as como los atributos width, height, name, extension y size.
Una instancia de la clase TextFile contiene los atributos summary, name, extension y
size.
Una instancia de la clase Mp3File contiene los atributos especficos de la clase Mp3File,
as como los atributos length, name, extension y size.
Introduccin
Colecciones
Clases Autocontenidas
Bucles de Relacin
Introduccin
Aunque la definicin de clases y sus relaciones depende de la aplicacin que se est
utilizando en particular, algunas estructuras de clase son comunes para muchos diseos.
Estas estructuras de clase, las cuales pueden concebirse como bloques de construccin
bsicos, pueden ser combinadas para la creacin de sistemas complejos. Esta pgina te
mostrar algunas de ellas.
Colecciones
Una coleccin modela una relacin uno a muchos. Las colecciones almacenan muchas
instancias de una clase. El siguiente diagrama de clase utiliza una conexin para representar
la relacin "un cliente tiene una o ms cuentas bancarias" y define los mtodos para
manejar la coleccin de instancias de la clase BankAccount (cuenta bancaria). En dicha
coleccin, cada instancia de BankAccount tiene un ndice que indica su ubicacin en la
coleccin.
Los ndices son una manera simple de trabajar con colecciones, pero no siempre son
apropiados para todos los tipos de colecciones. En la siguiente unidad de este curso, te
presentaremos una solucin ms general que no utiliza ndices.
Clases Autocontenidas
Una clase puede tener una asociacin con ella misma. En tales casos, la clase contiene
atributos con referencias a los objetos de la misma clase. Por ejemplo, el siguiente diagrama
de clase muestra la definicin de la clase Person en un sistema de rbol genealgico. Las
relaciones "cada persona tiene una madre" y "cada persona tiene un padre" estn
indicadas en los atributos mother y father. Los atributos mother y father son referencias
a objetos de la clase Person.
Bucles de Relacin
La autocontencin puede ser encontrada en relaciones que incluyen dos o ms clases. Un
ejemplo de un ciclo de autocontencin es un sistema de archivos. Un sistema de archivos
tiene carpetas y las carpetas contienen archivos o ms carpetas, o ambas. Podemos definir
una clase Folder, que contenga una coleccin de objetos FolderItem:
Introduccin
Crear el Proyecto
Crear la Carpeta
Crear el Nuevo Diagrama de Clase
Crear la Clase BankAccount
Crear la Clase Person
Crear la Clase Client
Crear una Relacin de Especializacin/Generalizacin
Crear una Relacin de Asociacin
Exportar una Imagen
Introduccin
EclipseUML es un plug-in de Eclipse para dibujar diagramas de UML. EclipseUML provee
una vista grfica para definir clases y sus relaciones. En esta pgina, mostraremos cmo
dibujar un diagrama de clase utilizando EclipseUML. Crearemos un diagrama de clase para
la siguiente abstraccin:
"En un sistema bancario, un cliente es una persona que tiene una o ms cuentas de banco"
Crear el Proyecto
El primer paso es crear un proyecto de Java:
1. En el men File, apunta a New y despus selecciona Project.
2. En el asistente de Nuevo Proyecto, selecciona Java en el panel izquierdo, da un clic
en Java Project que se encuentra a la derecha y despus presiona Next.
Crear la Carpeta
1. En el men File, apunta a New y despus da un clic en Folder. Aparecer el cuadro
de dilogo New Folder.
2. Escribe uml en el cuadro Folder name y despus presiona Finish.
. Presiona
Requerida:
o Barker, primera edicin, captulo 10 (pginas 213
30).
o Barker, segunda edicin, captulo 10 (pginas 355
72).
Secuencia: Leer el libro de texto antes de leer esta pgina.
Identificando Clases
Una manera sencilla de identificar las clases es analizar la descripcin textual en la
especificacin del sistema. En este anlisis textual, los sustantivos y las frases de
sustantivos indican con frecuencia los objetos y sus clases. Los sustantivos en singular
("libro", "catlogo de biblioteca" y "cliente") y los sustantivos en plural ("usuarios",
"libros" y "cuentas") indican clases. Los sustantivos propios ("el banco ACME") y los
sustantivos de referencia directa ("la persona que posea la cuenta") indican objetos.
Los pasos para identificar las clases utilizando el anlisis del texto son los siguientes:
Reducir la lista:
o Convertir los sustantivos en plural a su forma singular. En un modelo de
objetos, los nombres de clases estn en singular.
o Eliminar los sustantivos que representen objetos. Reemplazar con
sustantivos genricos. Por ejemplo, utiliza "cliente" en vez de "John Smith."
o Eliminar los sustantivos vagos.
o Eliminar los sustantivos que son atributos de clases. Si no puedes identificar
los atributos del sustantivo, es posible que el sustantivo haga referencia a un
atributo de la clase.
Agrupa los sinnimos y elige el mejor nombre para la clase a partir de este grupo.
Por ejemplo, "usuario" y "cliente" son sinnimos. En un sistema bancario, el mejor
nombre es "cliente" porque el sistema puede tener dos tipos de usuarios: los clientes
y los empleados del banco.
Identificando Relaciones
Los pasos para identificar las relaciones de asociacin y de especializacin/generalizacin
son los siguientes:
Crear una tabla n x n donde n es el nmero de clases. Nombra las filas y columnas
con los nombres de las clases.
La siguiente tabla muestra las relaciones del enunciado "un cliente es una persona que tiene
una o ms cuentas".
Persona
Cliente
Cuenta
Persona
Cliente
cuentas
Cuenta
Esta tabla indica que la clase Cliente es una especializacin de la clase Persona y la clase
Persona tiene una relacin de asociacin con la clase Cuenta.
Identificando Atributos
Los atributos son los datos que un objeto es responsable de conocer y administrar. Los
pasos para identificar los atributos de las clases son los siguientes:
Buscar los adjetivos y las frases posesivas como "X de Y" en la especificacin del
sistema. Por ejemplo, "nmero de la cuenta" y "nombre del cliente".
Identificando Mtodos
Los mtodos describen las acciones que un objeto es responsable de proveer. Los pasos
para identificar los mtodos de las clases son los siguientes:
Si el objeto tiene alguna coleccin, incluye los mtodos necesarios para aadir,
eliminar y acceder los elementos de estas colecciones.
Utilizar la notacin de clases para representar clases. Incluir los atributos y mtodos.
Referencias:
Lee, Richard, y William M. Tepfenhart. Practical Object-Oriented Development with UML
and Java (Desarrollo Orientado a Objetos Prctico con UML y Java). Upper Saddle River,
NJ: Prentice-Hall, 2002.
El sistema contiene una base de datos de los usuarios. Cada usuario tiene un cdigo de
identificacin nico, adems de un nombre. El sistema mantiene una lista, para cada
usuario, del catlogo de artculos que ste tiene prestados.
El sistema de biblioteca debe ser capaz de:
Identificando Clases
Primero, hacemos una lista de los sustantivos en la especificacin del sistema:
CD
artculos
grabacin
cinta
usuarios
copia
sistema
informacin
usuario
catlogo
artculo
cdigo de
identificacin
biblioteca
ttulo
nombre
tipos
ao
lista
usuario
libros
autor
cdigo (usuario)
grabaciones
nmeros de pgina
lista de artculos
prestados
cdigo (artculo)
intrprete
copias
formato
Entonces, reducimos la lista eliminando los siguientes nombres:
cdigo (artculo), ttulo, ao,
disponibilidad
intrprete, formato
CD, cinta
nombre, cdigo de
Estos nombres son atributos de un
identificacin, cdigo (usuario) usuario.
informacin
tipos
A continuacin, agrupamos los sinnimos y elegimos el mejor nombre para la clase de cada
grupo:
CatalogItem
LibrarySystem
Borrower
usuarios, usuario
Book
libros, libro
Recording
grabaciones, grabacin
BorrowedItems
BorrowerDatabase
Identificando Relaciones
La siguiente tabla identifica las relaciones de especializacin/generalizacin:
Identificando Atributos
A continuacin se presenta la lista de atributos para cada clase:
Clase
Atributos
LibrarySystem
catalog, borrowerDB
Catalog
items
CatalogItem
Book
author, numberOfPages
Recording
performer, format
Borrower
BorrowedItems
items
BorrowerDatabase
borrowers
Identificando Mtodos
A continuacin se presenta la lista de mtodos de cada clase:
Clase
Mtodos
LibrarySystem
displayCatalog()
displayCatalogItem()
displayBorrowerDatabase()
displayBorrower()
checkIn()
checkOut()
Catalog
addItem(item:CatalogItem)
getItem(index:int):CatalogItem
getNumberOfItems():int
getItem(code:String):CatalogItem
CatalogItem
getCode():String
getTitle():String
getYear():int
isAvailable():boolean
setAvailable(value:boolean)
Book
getAuthor():String
getNumberOfPages():int
Recording
getPerformer():String
getFormat():String
Borrower
getId():String
getName():String
getBorrowedItems():BorrowedItems
BorrowedItems
addItem(item:CatalogItem)
removeItem(item:CatalogItem)
getItem(index:int):CatalogItem
getItem(code:String):CatalogItem
getNumberOfItems():int
BorrowerDatabase addBorrower(borrower:Borrower)
getBorrower(index:int):Borrower
getNumberOfBorrowers():int
getBorrower(id:String):Borrower
Requeridas:
o Barker, primera edicin, captulo 3 (pginas 5962),
captulo 4 (pginas 83109), captulo 7 (pginas 17985), captulo 13 (pginas 326-33).
o Barker, segunda edicin, captulo 3 (pginas 6871),
captulo 4 (pginas 97161), captulo 7 (pginas 31320).
/**
* Esta clase modela un punto en el plano Cartesiano.
*
* @author
* @version 1.0.0
*/
public class Point {
/* Nmero de instancias creadas */
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111: }
getNumberOfInstances()
return Point.numberOfInstances;
}
/**
* Regresa la coordenada x de este punto.
*
* @return la coordenada x de este punto.
*/
public int getX() {
return this.x;
}
/**
* Regresa la coordenada y de este punto.
*
* @return Regresa la coordenada y de este punto.
*/
public int getY() {
return this.y;
}
/**
* Modifica la coordenada x de este punto.
*
* @param newX la nueva coordenada x
*/
public void setX(int newX) {
this.x = newX;
}
/**
* Modifica la coordenada y de este punto.
*
* @param newY la nueva coordenada y
*/
public void setY(int newY) {
this.y = newY;
}
Listado 1 Point.java
La siguiente figura muestra la salida de la consola cuando el mtodo principal de la clase
Point es ejecutado:
Por convencin, para llamar a un mtodo de clase, el nombre del mtodo debe estar
precedido por el nombre de la clase:
Point.getNumberOfInstances()
Esto tiene sentido porque las variables de clase no son parte de ningn objeto, por lo que
los mtodos que operan en ellos no estn asociados a ningn objeto en particular. Si las
variables de clase son pblicas, tambin son accedidas utilizando el nombre de la clase. Si
numberOfInstances fuera declarada como public, podramos escribir:
Point.numberOfInstances
Debido a que las variables de clase y los mtodos de clase no estn asociados a ningn
objeto en particular, pueden ser utilizados an y cuando no existan objetos de la clase! Por
ejemplo, podemos llamar a getNumberOfInstances antes de que se cree ningn objeto
Point.
En este material, utilizaremos el prefijo "initial" (inicial) para nombrar los parmetros de
los constructores y el prefijo "new" (nuevo) para nombrar los parmetros de los
modificadores. Esta convencin evita el error lgico que ocurre cuando un programador
utiliza el mismo nombre para un parmetro y para una variable de instancia y olvida utilizar
la palabra clave this.
2.1.2 Herencia
Requerida:
o Barker, primera edicin, captulo 5 (pginas 12039);
captulo 13 (pginas 305-11 and 33543).
o Barker, segunda edicin, captulo 5 (pginas 174
208).
Secuencia: Lee el libro de texto antes de leer esta pgina.
/**
* Esta clase modela una persona.
*
* @author
* @version 1.0.0
*/
public class Person {
/* Nombre de la persona */
private String name;
/* Direccin de la persona */
private String address;
/**
* Construye un objeto <code>Person</code>.
*
* @param initialName el nombre de la persona.
* @param initialAddress la direccin de la persona.
*/
public Person (String initialName, String initialAddress) {
this.name = initialName;
this.address = initialAddress;
}
/**
* Regresa el nombre de la persona.
*
* @return el nombre de la persona.
*/
public String getName() {
return this.name;
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46: }
}
/**
* Regresa la direccin de esta persona.
*
* @return la direccin de esta persona.
*/
public String getAddress() {
return this.address;
}
Listado 1 Person.java
A continuacin se presenta una implementacin de la clase Employee:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
/**
* Esta clase modela un Empleado (Employee).
*
* @author
* @version 1.0.0
*/
public class Employee extends Person {
/* Salario del empleado */
private double salary;
/**
* Construye un objeto <code>Employee</code>.
*
* @param initialName el nombre del empleado.
* @param initialAddress la direccin del empleado.
* @param initialSalary el salario del empleado.
*/
public Employee (String initialName, String initialAddress,
double initialSalary) {
super(initialName, initialAddress);
this.salary = initialSalary;
}
/**
* Regresa el salario de este empleado.
*
* @return el salario de este empleado.
*/
public double getSalary() {
return this.salary;
}
/**
* Modifica el salario de este empleado.
*
* @param newSalary el nuevo salario.
40:
41:
42:
43:
44:
45: }
*/
public void setSalary(double newSalary) {
this.salary = newSalary;
}
Listado 2 Employee.java
En la lnea 7 de Employee.java, la clase Employee extiende la clase Person. En la lnea
22, el constructor de Employee utiliza la palabra clave super para llamar al constructor de
Person, la clase padre. Las variables de instancia name y address son declaradas en la
clase Person, de modo que el constructor de Person las inicializar. En Java, dentro de un
constructor la llamada a super debe ser siempre la primera instruccin.
Observa que una instancia de la clase Employee contiene una copia de las variables name y
address, pero los mtodos de Employee no pueden acceder estas variables. Estas variables
son declaradas como privadas en la clase Person, de modo que slo pueden ser obtenidas
por los mtodos de la clase Person. Un objeto Employee debe utilizar los mtodos getName
y getAddress, ambos heredados de Person, para acceder a los valores de name y address,
respectivamente.
// ilegal
// legal
// legal
Java provee una facilidad para el problema de getSalary. Podemos cambiar la referencia
person en una referencia de Employee con el trmino de conversin de tipo (cast). Una
vez que tenemos una referencia de Employee, podemos llamar al mtodo getSalary como
se indica a continuacin:
Podemos convertir la referencia person en una referencia Employee porque person apunta
en realidad a un objeto Employee. Si no se hiciera y ejecutramos el cdigo, la conversin
sera ilegal y la mquina virtual de Java (Java Virtual Machine o JVM) lanzara una
excepcin ClassCastException.
Aunque siempre resulta legal convertir una referencia de subclase en una referencia de
superclase, hacerlo al revs no siempre es legal. Considera el siguiente cdigo:
Person person = new Person ("Joe Smith", "100 Main Ave");
double salary = ((Employee) person).getSalary();
// ilegal
Este cdigo compilar, pero cuando sea ejecutado, la JVM lanzar una excepcin
ClassCastException porque, en este ejemplo, la referencia person no apunta a un objeto
Employee.
El Operador instanceof
El operador instanceof toma dos operandos: una referencia de un objeto y un nombre de
clase. Una expresin instanceof se evaluar como verdadera si el objeto especificado es
una instancia de la clase especificada:
object instanceof ClassX
Mtodo equals
Mtodo toString
Lecturas:
Requeridas:
o Barker, primera edicin, captulo 13 (pginas 3625).
o Barker, segunda edicin, captulo 13 (pginas 523
32).
Mtodo equals
En Java, todas las clases descienden, directa o indirectamente, de la clase Object, de modo
que todas las clases heredan los mtodos definidos en la clase Object. En este curso,
utilizaremos fuertemente dos de estos mtodos, equals y toString.
El mtodo equals compara dos objetos y regresa verdadero s y solo si son iguales. La
versin de este mtodo definida en la clase Object regresa true si los objetos que estn
siendo comparados son el mismo objeto. Esta implementacin predeterminada es
exactamente lo mismo que obj1 == obj2.
El mtodo equals toma un parmetro de entrada, una referencia de Object. En Java, esto
significa que una referencia a un objeto de cualquier tipo puede ser pasada a equals. Por lo
mismo, equals puede utilizarse para comparar dos instancias de cualquier clase.
Recuerda la clase Point que estudiamos en la seccin Definiendo Clases. El siguiente
cdigo compara objetos Point utilizando el mtodo equals definido en la clase Object:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
14: } else {
15:
System.out.println("pointOne and pointThree are different");
16: }
Mtodo toString
La clase Object define un mtodo llamado toString que regresa la representacin string
del objeto que hace la llamada. La versin de este mtodo definida en la clase Object
regresa un String con el siguiente formato:
NombreClase@numero
/**
* Sobrescribe {@link Object#toString()}.
* <p>
* Regresa una representacin string de este objeto
* <code>Point</code>.
* </p>
*
* @return una representacin string de este objeto
*
<code>Point</code>.
*/
public String toString() {
return
En la lnea 13, los selectores getX y getY son utilizados para construir un String con el
siguiente formato:
(x,y)
Opcional:
o IPL Information Processing Ltd, Why Bother to Unit
Test? (Por qu preocuparse por la Prueba de
Unidades?) Este documento introduce el concepto de
prueba de unidades y discute sus ventajas.
Opcional:
o IPL Information Processing Ltd, Designing Unit Test
Cases (Diseando Casos de Prueba de Unidades).
Este documento describe diversas tcnicas para
disear casos de prueba de unidades.
/**
* Esta clase modela una cuenta de banco.
*
* @author
* @version 1.0.0
*/
public class BankAccount {
/* Saldo de la cuenta*/
private double balance;
/**
* Crea un nuevo objeto <code>BankAccount</code> con un saldo
* inicial de cero.
*/
public BankAccount() {
this.balance = 0.0;
}
/**
* Regresa el saldo de esta cuenta.
*
* @return el saldo de esta cuenta
*/
public double getBalance() {
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73: }
return this.balance;
}
/**
* Deposita dinero en la cuenta. Si la cantidad especificada es
* positiva, se actualiza el saldo de la cuenta.
*
* @param amount cantidad de dinero que se aadir al saldo.
* @return <code>verdadero</code> si el dinero es depositado;
*
<code>falso</code> de otro modo.
*/
public boolean deposit(double amount) {
if (amount > 0) {
this.balance += amount;
return true;
} else {
return false;
}
}
/**
* Retira dinero de esta cuenta. Si la cantidad especificada es
* positiva y la cuenta tiene suficientes fondos, el
* saldo de la cuenta es actualizado.
*
* @param amount cantidad de dinero que se sustraer del saldo.
* @return <code>verdadero</code> si el dinero es retirado;
*
<code>falso</code> de otro modo.
*/
public boolean withdraw(double amount) {
if (amount > 0 && this.balance >= amount) {
this.balance -= amount;
return true;
} else {
return false;
}
}
Listado 1 BankAccount.java
La clase BankAccount contiene tres mtodos: uno para acceder el saldo de la cuenta; uno
para depositar dinero y otro para retirar dinero. Los mtodos deposit y withdraw tienen
cdigo defensivo: deposit no actualizar el saldo si la cantidad especificada es negativa (o
cero), mientras que withdraw no actualizar el saldo si la cuenta no tiene fondos
insuficientes. La siguiente clase es una clase manejadora de prueba para BankAccount:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
import
java.io.*;
/**
* Programa de prueba para la clase <code>BankAccount</code>.
*
* @author
* @version 1.0.0
*/
public class TestBankAccount {
/* Flujo de salida estndar */
private static PrintWriter stdOut =
new PrintWriter(System.out, true);
/* Flujo de error estndar */
private static PrintWriter stdErr =
new PrintWriter(System.err, true);
/**
* Programa de prueba para la clase <code>BankAccount</code>.
*
* @param args no utilizado.
*/
public static void main(String[] args) {
boolean result;
// Probando el constructor y el accesor
BankAccount accountOne = new BankAccount();
assertTrue("1: testing method getBalance()",
accountOne.getBalance() == 0);
//Probando el mtodo deposit
BankAccount accountTwo = new BankAccount();
result = accountTwo.deposit(100);
assertTrue("2: testing method deposit", result);
assertTrue("3: testing method deposit",
accountTwo.getBalance() == 100);
result = accountTwo.deposit(50);
assertTrue("4: testing method deposit", result);
assertTrue("5: testing method deposit",
accountTwo.getBalance() == 150);
result = accountTwo.deposit(0);
assertTrue("6: testing method deposit", ! result);
assertTrue("7: testing method deposit",
accountTwo.getBalance() == 150);
result = accountTwo.deposit(-25);
assertTrue("8: testing method deposit", ! result);
assertTrue("9: testing method deposit",
accountTwo.getBalance() == 150);
//Probando el mtodo withdraw
58:
BankAccount accountThree = new BankAccount();
59:
60:
accountThree.deposit(100);
61:
result = accountThree.withdraw(60);
62:
assertTrue("10: testing method withdraw", result);
63:
assertTrue("11: testing method withdraw",
64:
accountThree.getBalance() == 40);
65:
66:
result = accountThree.withdraw(50);
67:
assertTrue("12: testing method withdraw", ! result);
68:
assertTrue("13: testing method withdraw",
69:
accountThree.getBalance() == 40);
70:
71:
result = accountThree.withdraw(0);
72:
assertTrue("14: testing method withdraw", ! result);
73:
assertTrue("15: testing method withdraw",
74:
accountThree.getBalance() == 40);
75:
76:
result = accountThree.withdraw(-10);
77:
assertTrue("16: testing method withdraw", ! result);
78:
assertTrue("17: testing method withdraw",
79:
accountThree.getBalance() == 40);
80:
81:
stdOut.println("done");
82:
}
83:
84:
/**
85:
* Despliega un mensaje en el flujo de salida estndar si el
86: valor
87:
* especificado por el argumento <code>condition<code> es
88:
* <code>falso</code>.
89:
*
90:
* @param message el mensaje de error.
91:
* @param condition la condicin de prueba.
92:
*/
93:
public static void assertTrue(String message,
94:
boolean condition) {
95:
96:
if (! condition) {
97:
stdErr.print("** Test failure ");
98:
stdErr.println(message);
99:
}
100:
}
}
Listado 2 TestBankAccount.java
Observa que el operador -! est separado de su operando por un espacio para enfatizar la
negacin de la expresin.
El mtodo assertTrue facilita la escritura de casos de prueba. Tiene dos parmetros de
entrada: un String y un boolean. El primer argumento debe ser un mensaje de error. El
mensaje ser desplegado si el segundo argumento indica algn problema. El segundo
argumento debe ser el resultado de una prueba o una expresin de prueba, tal como:
accountTwo.getBalance() == 100
El mtodo main de la clase de prueba comienza con un caso de prueba para el constructor
de BankAccount y el selector getBalance. Contina con diversos casos de prueba para el
mtodo deposit; los casos de prueba aseguran que deposit trabaja correctamente tanto
con argumentos vlidos como invlidos. Concluye con casos de prueba para withdraw que
consideran varios escenarios posibles.
La Clase CatalogItem
La Clase CatalogItem modela un elemento del catlogo de la biblioteca.
Variables de instancia:
Constructor y mtodos:
String
la clase
Los campos estn separados por un guin bajo ( _ ). Suponemos que los campos en
s no contienen guiones bajos.
Implementacin:
1:
2:
3:
4:
5:
6:
7:
/**
* Esta clase modela un artculo del catlogo. Contiene la siguiente
* informacin:
* </p>
* <ol>
* <li>el cdigo del artculo, un <code>String</code></li>
* <li>el ttulo del artculo, un <code>String</code></li>
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
this.code;
}
/**
* Regresa el ttulo de este artculo.
*
* @return el ttulo de este artculo.
65:
*/
66:
public String getTitle() {
67:
68:
return this.title;
69:
}
70:
71:
/**
72:
* Regresa el ao en que el artculo fue publicado.
73:
*
74:
* @return el ao en que el artculo fue publicado.
75:
*/
76:
public int getYear() {
77:
78:
return this.year;
79:
}
80:
81:
/**
82:
* Establece la variable de instancia <code>available</code>.
83:
*
84:
* @param value el nuevo valor.
85:
*/
86:
public void setAvailable(boolean value) {
87:
88:
this.available = value;
89:
}
90:
91:
/**
92:
* Regresa <code>true</code> si el artculo est disponible.
93:
*
94:
* @return <code>true</code> si el artculo est disponible;
95:
*
<code>false</code> de otra forma.
96:
*/
97:
public boolean isAvailable() {
98:
99:
return this.available;
100:
}
101:
102:
/**
103:
* Regresa <code>true</code> si el cdigo de este artculo del
104: catlogo es
105:
* igual al cdigo del argumento
106:
* </p>
107:
*
108:
* @param object objeto contra el cual se compara este artculo
109: del catlogo.
110:
* @return <code>true</code> si el cdigo de este artculo del
111: catlogo es
112:
*
igual al cdigo del argumento; <code>false</code>
113:
*
de otro modo.
114:
*/
115:
public boolean equals(Object object) {
116:
117:
return object instanceof CatalogItem
118:
&& getCode().equals(((CatalogItem) object).getCode());
119:
}
120:
121:
/**
122:
* Regresa la representacin string de este artculo del
123: catlogo.
124:
*
125:
* @return la representacin string de este artculo del
126: catlogo.
127:
*/
public String toString() {
return
}
}
Listado 1 CatalogItem.java
La Clase Book
La clase Book modela un libro. Extiende la clase CatalogItem.
Variables de instancia:
Constructor y mtodos:
Constructor que inicializa las variables de instancia code, title, year, available,
author y numberOfPages.
formato:
code_title_year_available_author_numberOfPages
Los campos estn separados por un guin bajo ( _ ). Suponemos que los campos no
contienen ningn guin bajo.
Implementacin:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
/**
* Esta clase modela un libro. Extiende {@link CatalogItem} y
* aade la siguiente informacin:
* <ol>
* <li>el autor del libro, un <code>String</code></li>
* <li>el nmero de pginas del libro, un <code>int</code></li>
* </ol>
*
* @author
* @version 1.0.0
* @see CatalogItem
*/
public class Book extends CatalogItem {
/* Autor del libro.*/
private String author;
/* Nmero de pginas del libro.*/
private int numberOfPages;
/**
* Construye un objeto <code>Book</code>.
*
* @param initialCode el cdigo del libro.
* @param initialTitle el ttulo del libro.
* @param initialYear el ao en que fue publicado el libro.
* @param initialAuthor el autor del libro.
* @param initialNumberOfPages el nmero de pginas del libro.
*/
public Book(String initialCode, String initialTitle,
int initialYear, String initialAuthor,
int initialNumberOfPages) {
super(initialCode, initialTitle, initialYear);
this.author = initialAuthor;
this.numberOfPages = initialNumberOfPages;
}
/**
* Regresa el autor de este libro.
*
* @return el autor de este libro.
*/
public String getAuthor() {
return
this.author;
}
/**
* Regresa el nmero de pginas de este libro.
*
* @return el nmero de pginas de este libro.
*/
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70: }
public int
return
getNumberOfPages()
this.numberOfPages;
}
/**
* Regresa la representacin string de este libro.
*
* @return la representacin string de este libro.
*/
public String toString() {
return
Listado 2 Book.java
La Clase Recording
La clase Recording modela una grabacin, ya sea un CD o una cinta. Extiende la clase
CatalogItem.
Variables de instancia:
performer. El intrprete
format. El formato de la
de la grabacin
grabacin
Constructor y mtodos:
Constructor que inicializa las variables de instancia code, title, year, available,
performer y format.
siguiente formato:
code_year_available_title_performer_format
Regresa
tiene el
Los campos estn separados por un guin bajo ( _ ). Suponemos que los campos no
contienen guiones bajos.
Implementacin:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
/**
* Esta clase modela una grabacin. Extiende {@link CatalogItem} y
* aade la siguiente informacin:
* <ol>
* <li>el intrprete de la grabacin, un <code>String</code></li>
* <li>el formato de la grabacin, un <code>String</code></li>
* </ol>
*
* @author
* @version 1.0.0
* @see CatalogItem
*/
public class Recording extends CatalogItem {
/* Intrprete de la grabacin. */
private String performer;
/* Formato de la grabacin. */
private String format;
/**
* Construye un objeto <code>Recording</code>.
*
* @param initialCode el cdigo del catlogo de artculos.
* @param initialTitle el ttulo del catlogo de artculos.
* @param initialYear el ao del catlogo de artculos.
* @param initialPerformer el intrprete de la grabacin.
* @param initialFormat el formato de la grabacin.
*/
public Recording(String initialCode, String initialTitle,
int initialYear, String initialPerformer,
String initialFormat) {
super(initialCode, initialTitle, initialYear);
this.performer = initialPerformer;
this.format = initialFormat;
}
/**
* Regresa el intrprete de esta grabacin.
*
* @return el intrprete de esta grabacin.
*/
public String getPerformer() {
return
}
/**
this.performer;
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70: }
this.format;
}
/**
* Regresa la representacin string de esta grabacin.
*
* @return la representacin string de esta grabacin.
*/
public String toString() {
return
Listado 3 Recording.java
La Clase Borrower
La clase Borrower modela un usuario de la biblioteca.
Variables de instancia:
del usuario
Constructor y mtodos:
iguales.
siguiente formato:
id_name
Los campos estn separados por un guin bajo ( _ ). Suponemos que los campos no
contienen guiones bajos.
Implementacin:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
/**
* Esta clase modela un usuario de una biblioteca. Contiene la
siguiente
* informacin:
* <ol>
* <li>El id del usuario, un <code>String</code></li>
* <li>El nombre del usuario, un <code>String</code></li>
* <li>Los artculos que han sido prestados al usuario,
*
un objeto <code>BorrowedItems</code></li>
* </ol>
*
* @author
* @version 1.0.0
* @see BorrowedItems
* @see CatalogItem
*/
public class Borrower {
/* Nmero de identificacin del usuario.*/
private String id;
/* Nombre del usuario.*/
private String name;
/* Artculos prestados al usuario.*/
private BorrowedItems borrowedItems;
/**
* Construye un objeto <code>Borrower</code>.
* <p>
* La coleccin de artculos prestados inicialmente est vaca.
* </p>
*
* @param initialId el id del usuario.
* @param initialName el nombre del usuario.
*/
public Borrower(String initialId, String initialName) {
this.id = initialId;
this.name = initialName;
this.borrowedItems = new BorrowedItems();
}
/**
* Regresa el nmero de identificacin de este usuario.
*
* @return el nmero de identificacin de este usuario.
*/
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
public String
return
getId()
this.id;
}
/**
* Regresa el nombre de este usuario.
*
* @return el nombre de este usuario.
*/
public String getName () {
return
this.name;
}
/**
* Regresa la coleccin de artculos prestados.
*
* @return un objeto {@link BorrowedItems}.
*/
public BorrowedItems getBorrowedItems () {
return
this.borrowedItems;
}
/**
* Regresa <code>true</code> si el id de este usuario es
* igual al id del argumento.
*
* @param object objeto contra el cual se compara este usuario.
* @return <code>true</code> si el id de este usuario es
*
igual al id del argumento; <code>false</code>
*
de otro modo.
*/
public boolean equals(Object object) {
return object instanceof Borrower
&& getId().equals(((Borrower) object).getId());
}
/**
* Regresa la representacin string de este usuario.
*
* @return la representacin string de este usuario.
*/
public String toString() {
return
}
}
Listado 4 Borrower.java
2.2 Colecciones
2.2.1 Arreglos
2.2.2 ArrayList e Iteradores
2.2.3 Implementando las Colecciones del Sistema de Biblioteca
2.2.1 Arreglos
Arreglos
Declaracin y Utilizacin de Arreglos
Un Ejemplo del Uso de Arreglos
Lecturas:
Requeridas:
o Barker, primera edicin, captulo 6 (pginas 1438);
captulo 13 (pginas 3168).
o Barker, segunda edicin, captulo 6 (pginas 219
27).
Arreglos
Un arreglo es un agregado homogneo, es decir, una coleccin de datos (cada uno de los
cuales es del mismo tipo). En Java, un arreglo puede contener un conjunto de datos
primitivos o un conjunto de referencias de objetos. Cada pieza del arreglo se llama
elemento. Para acceder a un elemento de un arreglo, utiliza el operador de corchetes ( [] ) y
un ndice entero que indica la ubicacin del elemento en el arreglo. El primer elemento en
un arreglo tiene un ndice 0, el segundo tiene un ndice 1 y as sucesivamente. Por lo tanto,
los ndices en un arreglo de n elementos estarn en el rango de 0 a n - 1. Los elementos
del arreglo son almacenados contiguamente en memoria.
ages;
El tipo de los elementos del arreglo es int, mientras que el tipo del arreglo en s es int[].
El nombre del arreglo es el identificador ages. Considera otra declaracin:
String[]
names;
Esta instruccin declara un arreglo de tipo String, una coleccin de referencias String.
Las variables ages y names son variables de referencia y sus valores son null inicialmente.
Cada una de ellas permanecer siendo null hasta que se cree un objeto arreglo. (En Java,
los arreglos son implementados como objetos).
Para crear un objeto arreglo, utiliza el operador new, seguido por el tipo de los elementos y
el tamao del arreglo deseado. El tamao del arreglo no debe ser negativo.
Cuando se crea un nuevo objeto arreglo, sus elementos son inicializados a sus valores
predeterminados. Por ejemplo, los elementos del arreglo ages son inicializados en cero y
los elementos del arreglo names son inicializados en null. Un objeto arreglo contiene una
variable de instancia public llamada length, la cual indica el nmero de elementos del
arreglo. La longitud de un objeto arreglo no puede cambiar nunca. Sin embargo, una
referencia de un arreglo puede ser cambiada de modo que haga referencia a otro objeto
arreglo, con una longitud diferente. Considera lo siguiente:
int[] values = new int[5];
int[] biggerArray = new int[10];
int nextIndex = 0;
...
if (nextIndex >= values.length) {
values = biggerArray;
}
La longitud del arreglo se deduce del nmero de elementos del inicializador. En el arreglo
ages, el primer elemento (el elemento que se encuentra en la posicin 0) se establece como
21; el segundo elemento como 19 y as sucesivamente. En el arreglo names, los primeros
dos elementos hacen referencia a objetos String, mientras que la ltima referencia es
null.
Recuerda que un elemento del arreglo es accedido utilizando el operador de corchetes y un
ndice. Considera la siguiente expresin. El primer elemento tienen un ndice 0, por lo que
el ndice 2 indica el tercer elemento del arreglo:
ages[2]
La
// el tercer elemento
Mquina
Virtual
de
Java
(JVM)
lanzar
una
excepcin
ArrayIndexOutOfBoundsException si un programa trata de utilizar un ndice invlido. Un
ndice negativo siempre es invlido. Si un arreglo contiene n elementos, entonces un ndice
n o mayor es invlido.
Debido a que ages es un arreglo de enteros (int), la expresin ages[2] es un int. De
forma similar, names es un arreglo de referencias String de modo que la expresin
es una referencia a un objeto String y puede ser utilizado cada vez que se
requiera una referencia String. De este modo, si:
names[1]
entonces, la siguiente expresin resultar false porque el primer y el segundo elemento del
arreglo hacen referencia a objetos String que no son iguales.
names[0].equals(names[1])
Tpicamente, los arreglos son recorridos en orden secuencial utilizando bucles for. El
siguiente cdigo utiliza un bucle for para inicializar cada elemento en un arreglo en el
cuadrado de su ndice. Despus de que el bucle termina, el elemento cuyo ndice es 0 tiene
un valor de 0, el elemento cuyo ndice es 1 tiene un valor de 1, el elemento cuyo ndice es 2
tiene un valor de 4 y as sucesivamente.
int[]
values = new
int[5];
La variable de control del bucle, i, tiene dos propsitos en el cuerpo del bucle: 1) es
utilizada como el ndice del arreglo y 2) es utilizada para calcular el valor de cada elemento
del arreglo. Observa que values.length es parte de la condicin de terminacin del bucle.
El bucle for-each provee una manera sencilla para iterar sobre los elementos de un arreglo.
En el bucle for-each se debe especificar el arreglo sobre el cual se realizar la iteracin, y
una variable para acceder a cada uno de los elementos. Por ejemplo, el siguiente cdigo
utiliza el bucle for-each para concatenar las cadenas que se encuentran en un arreglo y
despus despliega el resultado: "Arrays and for-each".
String[] words = {"Arrays", " and ", "for-each"}
String result = "";
for (String element : words) {
result += element;
}
stdout.println(result);
import java.io.*;
/**
* Esta clase modela un diccionario
*
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103: de
104:
105:
106:
107:
108: de
109:
110:
111:
112:
113:
114:
}
stdOut.println("done");
}
/**
* Crea un diccionario vaco.
*/
public Dictionary() {
this.words = new String[INITIAL_SIZE];
this.nextIndex = 0;
}
/**
* Aade una nueva palabra a este diccionario.
*
* @param word la palabra que ser aadida.
*/
public void addWord(String word) {
if (this.nextIndex >= this.words.length) {
// crea un nuevo arreglo, que tiene el doble del tamao
// del arreglo actual
String[] biggerWords = new String[2 * this.words.length];
// copia los contenidos del arreglo actual
// al nuevo arreglo
for (int i = 0; i < this.words.length; i++) {
biggerWords[i] = this.words[i];
}
this.words = biggerWords;
}
this.words[this.nextIndex] = word;
this.nextIndex++;
}
/**
* Regresa <code>true</code> si la palabra especificada es parte
* este diccionario.
*
* @param word la palabra que ser buscada.
* @return <code>true</code> si la palabra especificada es parte
*
este diccionario; <code>false</code> de otra forma.
*/
public boolean hasWord(String word) {
for (int i = 0; i < this.nextIndex; i++) {
if (this.words[i].equals(word)) {
return true;
}
}
return false;
}
Listado 1 Dictionary.java
Las palabras del diccionario son almacenadas en un arreglo String. En la lnea 78, el
mtodo addWord aade una palabra al arreglo. Inicialmente, el arreglo puede almacenar
cinco cadenas. Si addWord es llamada y el arreglo est lleno, addWord crea un nuevo
arreglo (el cual tiene el doble del tamao del arreglo actual), copia los contenidos del
arreglo actual al nuevo arreglo y entonces actualiza la referencia del arreglo de modo que
apunte al nuevo arreglo.
En la lnea 105, el mtodo hasWord determina si la palabra especificada es parte del
diccionario. Busca en el arreglo secuencialmente, comenzando con el elemento 0 (es decir,
el primer elemento que se encuentra en el ndice 0).
En la lnea 33, el mtodo main prueba la implementacin de la clase Dictionary utilizando
dos arreglos: knownWords y unknownWords. En la lnea 41, el bucle for-each aade al
diccionario las cadenas de caracteres del arreglo knownWords. En la lnea 45, el bucle foreach verifica que las cadenas de caracteres hayan sido aadidas al diccionario. Por ltimo,
en la lnea 53, el bucle for-each verifica que las cadenas de caracteres del arreglo
unknownWords no sean parte del diccionario.
La clase ArrayList
Iteradores
Utilizando Bucles For-Each en Colecciones
Implementando Clases Colecciones
Lecturas:
Requerida:
o Barker, primera edicin, captulo 13 (pginas 3436).
o Barker, segunda edicin, captulo 6 (pginas 227-40,
pginas 249-59); captulo 13 (pginas 3168).
Nota: La primera edicin no cubre el uso de la clase
ArrayList y genricos.
La Clase ArrayList
La clase java.util.ArrayList<E> implementa una coleccin de objetos que puede crecer
para alojar nuevos elementos cuando la coleccin est llena. Los objetos contenidos en el
ArrayList pueden ser accedidos utilizando un ndice entero. A continuacin se presenta
una lista de algunos de los mtodos definidos en la clase ArrayList:
ArrayList().
int size().
boolean isEmpty().
E get(int index).
E remove(int index).
Debido a que las colecciones solamente contienen referencias a objetos en lugar de tipos
primitivos, los elementos de tipos primitivos deben ser colocados en un objeto envoltorio
(wrapper) antes de ser colocados en una coleccin (por ejemplo, Integer en el caso de
elementos de tipo int). Java tiene la habilidad de automticamente envolver (box) y
desenvolver (unbox) tipos primitivos, reduciendo de esta manera la complejidad para aadir
y acceder elementos de tipos primitivos en las colecciones. El siguiente cdigo ilustra cmo
utilizar un ArrayList de enteros:
ArrayList<Integer> numbers = new ArrayList<Integer>();
numbers.add(1);
int num = numbers.get(0);
Iteradores
El mtodo iterator de la clase ArrayList regresa un objeto java.util.Iterator<E>
sobre los elementos de la coleccin. Un iterador es un objeto que se utiliza para recorrer
una coleccin de principio a fin. Adems, el uso de iteradores permite eliminar elementos
de la coleccin de forma segura durante el recorrido.
La clase java.util.Iterator<E> provee los siguientes mtodos:
boolean hasNext()
E next().
void remove().
Por ejemplo, el siguiente cdigo concatena las cadenas que se encuentran en una coleccin
y despus despliega el resultado: "ArrayList and Iterators".
ArrayList<String> list = new ArrayList<String>();
list.add("ArrayList");
list.add(" and ");
list.add("Iterators");
String result = "";
for (Iterator<String> listIterator = list.iterator();
listIterator.hasNext(); ) {
result += listIterator.next();
}
stdout.println(result);
import java.util.*;
import java.io.*;
/**
* Esta clase modela un diccionario
*
* @author
* @version 1.0.0
*/
public class Dictionary {
/* Flujo de salida estndar */
private static PrintWriter stdOut =
new PrintWriter(System.out, true);
/* Flujo de error estndar */
private static PrintWriter stdErr =
new PrintWriter(System.err, true);
/* Palabras en el diccionario */
private ArrayList<String> words;
/**
* Prueba la implementacin de la clase <code>Dictionary</code>.
*
* @param args no utilizado.
*/
public static void main(String[] args) {
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
*
87:
* @param word la palabra que ser aadida.
88:
*/
89:
public void addWord(String word) {
90:
91:
this.words.add(word);
92:
}
93:
94:
/**
95:
* Regresa <code>true</code> si la palabra especificada
96:
* se encuentra en este diccionario.
97:
*
98:
* @param word la palabra que ser buscada.
99:
* @return <code>true</code> si la palabra especificada es parte
100:
*
de este diccionario; <code>false</code> de otro modo.
101:
*/
102:
public boolean hasWord(String word) {
103:
104:
return this.words.contains(word);
105:
}
106:
107:
/**
108:
* Regresa una coleccin con todas las palabras en este
109: diccionario que
110:
* empiezan con el prefijo especificado.
111:
*
112:
* @param prefix el prefijo.
113:
* @return un <code>ArrayList</code> de todas las palabras en
114: este
115:
*
diccionario que empiezan con el prefijo especificado.
116:
*/
117:
public ArrayList<String> getStartsWith(String prefix) {
118:
119:
ArrayList<String> result = new ArrayList<String>();
120:
121:
for (Iterator<String> wordsIterator = this.words.iterator();
122:
wordsIterator.hasNext(); ) {
123:
124:
String word = wordsIterator.next();
125:
126:
if (word.startsWith(prefix)) {
127:
result.add(word);
128:
}
129:
}
130:
131:
return result;
132:
}
133:
134:
/**
135:
* Elimina todas las palabras de este diccionario que
136:
* empiezan con el prefijo especificado.
137:
*
138:
* @param prefix el prefijo.
139:
*/
140:
public void removeStartsWith(String prefix) {
141:
142:
for (Iterator<String> wordsIterator = this.words.iterator();
143:
144:
145:
146:
wordsIterator.hasNext(); ) {
String word = wordsIterator.next();
if (word.startsWith(prefix)) {
wordsIterator.remove();
}
}
}
}
Listado 1 Dictionary.java
Las palabras del diccionario son almacenadas en una coleccin ArrayList. En la lnea 87,
el mtodo addWord llama al mtodo add de la clase ArrayList para aadir una palabra al
diccionario.
En la lnea 100, el mtodo hasWord llama al mtodo contains de la clase ArrayList para
determinar si la palabra especificada se encuentra en el diccionario.
En la lnea 115, el mtodo getStartsWith utiliza un iterador para recorrer el diccionario y
regresa un ArrayList con todas las palabras del diccionario que empiezan con el prefijo
especificado.
En la lnea 142, el mtodo removeStartsWith llama al mtodo remove de la clase
Iterator para eliminar una palabra del diccionario.
El bucle for-each solamente puede ser utilizado en aquellas clases que implementan la
interfaz java.util.Iterable<T>. Una interfaz es una construccin en el lenguaje de
programacin Java que define un grupo de mtodos que se estn implementados por una
clase. Aprender ms sobre interfaces en la seccin Interfaces.
Para implementar la interfaz Iterable<T>, la clase debe incluir en la declaracin una
clusula implements y declarar el mtodo iterator.
1: public class MyCollection implements Iterable<T>
2:
3:
...
4:
5:
public Iterator<T> iterator() {
6:
...
7:
}
8: }
9:
import
java.util.*;
/**
* Esta clase modela un cliente de un banco. Se mantiene la siguiente
* informacin:
* <ol>
* <li>El nombre del cliente, un <code>String</code></li>
* <li>Las cuentas de banco del cliente, un
<code>ArrayList</code></li>
* </ol>
*
* @author
* @version 1.0.0
*/
public class Client implements Iterable<BankAccount> {
/* Nombre del cliente */
private String name;
/* Coleccin de objetos <code>BankAccounts</code>.*/
private ArrayList<BankAccount> accounts;
/**
* Construye un objeto <code>Client</code>.
* <p>
* Crea una coleccin vaca de cuentas de banco.
* </p>
*
* @param initialName el nombre del cliente.
*/
public Client(String initialName) {
this.name = initialName;
this.accounts = new ArrayList<BankAccount>();
}
/**
* Regresa el nombre de este cliente.
*
* @return el nombre de este cliente.
*/
public String getName() {
return this.name;
}
/**
* Aade una cuenta de banco a este cliente.
*
* @param bankAccount el objeto {@link BankAccount}.
*/
public void addAccount(BankAccount bankAccount) {
this.accounts.add(bankAccount);
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77: }
}
/**
* Regresa un iterador sobre las cuentas de banco de este cliente.
*
* regresa un {@link Iterator} sobre las cuentas de banco de este
*
cliente.
*/
public Iterator<BankAccount> iterator() {
return this.accounts.iterator();
}
/**
* Regresa el nmero de cuentas de banco de este cliente.
*
* @return el nmero de cuentas de banco de este cliente.
*/
public int getNumberOfAccounts() {
return this.accounts.size();
}
Listado 3 Client.java
La clase Client utiliza un ArrayList para implementar la coleccin de objetos
BankAccount. La clase implemente la interfaz Iterable<BankAccount>, provee el mtodo
addAccount para aadir un objeto BankAccount a la coleccin, y provee el mtodo
iterator para acceder a los objetos BankAccount almacenados en la coleccin.
El siguiente cdigo muestra cmo utilizar la clase Client:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
import
import
java.util.*;
java.io.*;
/**
* Programa de prueba para la clase <code>Client</code>.
*
* @author
* @version 1.0.0
*/
public class TestClient {
/* Standard output stream */
private static PrintWriter stdOut =
new PrintWriter(System.out, true);
/* Standard error stream */
private static PrintWriter stdErr =
new PrintWriter(System.err, true);
/**
* Prueba la implementacin de la clase <code>Client</code>.
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53: }
54:
*
* @param args no utilizado.
*/
public static void main(String[] args) {
BankAccount accountOne = new BankAccount();
BankAccount accountTwo = new BankAccount();
BankAccount accountThree = new BankAccount();
accountOne.deposit(1000.0);
accountTwo.deposit(2000.0);
accountThree.deposit(3000.0);
Client client= new Client("John Smith");
client.addAccount(accountOne);
client.addAccount(accountTwo);
client.addAccount(accountThree);
double totalBalance = 0.0;
for (BankAccount account : client) {
totalBalance += account.getBalance();
}
if (totalBalance != 6000.0) {
stdErr.println("** Test failure");
}
stdOut.println("done");
}
Listado 4 TestClient.java
La clase TestClient crea una instancia Client con tres cuentas bancarias. En la lnea 43,
la clase utiliza un bucle for-each para iterar sobre las cuentas del cliente y obtener su
balance.
Catalog
BorrowedItems
BorrowerDatabase
La Clase
Catalog
Constructor y mtodos:
public Catalog().
public
void
addItem(CatalogItem
catalogItem).
Aade el
artculo
especificado al catlogo.
public
Implementacin:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
import java.util.*;
import java.io.*;
/**
* Mantiene la informacin sobre un catlogo de una biblioteca.
* Contiene una coleccin de objetos {@link CatalogItem}.
*
* @author
* @version 1.0.0
* @see CatalogItem
*/
public class Catalog implements Iterable<CatalogItem> {
14:
/* Coleccin de objetos <code>CatalogItem</code>.*/
15:
private ArrayList<CatalogItem> items;
16:
17:
/**
18:
* Construye un string vaco.
19:
*/
20:
public Catalog() {
21:
22:
this.items = new ArrayList<CatalogItem>();
23:
}
24:
25:
/**
26:
* Aade un objeto {@link CatalogItem} a este catlogo.
27:
*
28:
* @param catalogItem el objeto {@link CatalogItem}.
29:
*/
30:
public void addItem(CatalogItem catalogItem) {
31:
32:
this.items.add(catalogItem);
33:
}
34:
35:
/**
36:
* Regresa un iterador sobre los artculos de este catlogo.
37:
*
38:
* @return un {@link Iterator} de objetos {@link CatalogItem}.
39:
*/
40:
public Iterator<CatalogItem> iterator() {
41:
42:
return this.items.iterator();
43:
}
44:
45:
/**
46:
* Regresa un objeto {@link CatalogItem} con el <code>code</code>
47:
* especificado.
48:
*
49:
* @param code el cdigo de un artculo.
50:
* @return El objeto {@link CatalogItem} con el cdigo
51:
*
especificado. Regresa <code>null</code> si el objeto
52: con
53:
*
el cdigo no es encontrado.
54:
*/
55:
public CatalogItem getItem(String code) {
56:
57:
for (CatalogItem catalogItem : items) {
58:
if (catalogItem.getCode().equals(code)) {
59:
60:
return catalogItem;
61:
}
62:
}
63:
64:
return null;
65:
}
66:
67:
/**
68:
* Regresa el nmero de artculos del catlogo.
69:
*
70:
* @return el nmero de objetos {@link CatalogItem} en este
71:
72:
73:
74:
75:
76:
*
catlogo
*/
public int getNumberOfItems()
return this.items.size();
}
}
Listado 1 Catalog.java
La Clase BorrowedItems
La clase BorrowedItems modela la lista de artculos que han sido prestados a un usuario.
Utiliza una coleccin de instancias de CatalogItem e implementa la interfaz
Iterable<CatalogItem> para permitir la iteracin sobre los artculos prestados utilizando
bucles for-each.
Variables de instancia:
Constructor y mtodos:
public BorrowedItems().
public
void
addItem(CatalogItem
catalogItem).
Aade el
artculo
public
artculos prestados.
Implementacin:
1:
2:
3:
4:
5:
6:
7:
8:
9:
import java.util.*;
import java.text.*;
/**
* Mantiene una coleccin de {@link CatalogItems}
* prestados a un usuario.
*
* @author
* @version 1.0.0
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
* @see CatalogItem
*/
public class BorrowedItems implements Iterable<CatalogItem>
67:
*
especificado. Regresa <code>null</code> no se
68: encuentra
69:
*
el objeto con el cdigo.
70:
*/
71:
public CatalogItem getItem(String code) {
72:
73:
for (CatalogItem catalogItem : this.items) {
74:
if (catalogItem.getCode().equals(code)) {
75:
76:
return catalogItem;
77:
}
78:
}
79:
80:
return null;
81:
}
82:
83:
/**
84:
* Regresa el nmero de artculos prestados.
85:
*
86:
* @return el nmero de artculos prestados.
87:
*/
88:
public int getNumberOfItems() {
89:
90:
return this.items.size();
}
}
Listado 2 BorrowedItems.java
La Clase BorrowerDatabase
La clase BorrowerDatabase modela una base de datos de usuarios. Utiliza una coleccin
de instancias de Borrower e implementa la interfaz Iterable<Borrower> para permitir la
iteracin sobre los elementos de la base de datos utilizando bucles for-each.
Variables de instancia:
borrowers. Una
clase Borrower.
Constructor y mtodos:
public BorrowerDatabase().
vaco.
public
String
addBorrower(Borrower
borrower).
Aade
el
usuario
public
datos de usuarios.
datos.
Implementacin:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
import java.util.*;
import java.text.*;
/**
* Mantiene una coleccin de objetos {@link Borrower}.
*
* @author
* @version 1.0.0
* @see Borrower
*/
public class BorrowerDatabase implements Iterable<Borrower>
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77: }
*
* @param id el id del usuario.
* @return El objeto {@link Borrower} con el id especificado.
*
Regresa <code>null</code> si el objeto con el id
*
especificado no es encontrado.
*/
public Borrower getBorrower(String id) {
for (Borrower borrower : this.borrowers) {
if (borrower.getId().equals(id)) {
return borrower;
}
}
return null;
}
/**
* Regresa el nmero de usuarios en esta
* base de datos.
*
* @return el nmero de usuarios en esta
*
base de datos.
*/
public int getNumberOfBorrowers() {
return this.borrowers.size();
}
Listado 3 BorrowerDatabase.java
.
Requeridas:
o Barker, primera edicin, captulo 7 (pginas 16975).
o Barker, segunda edicin, captulo 7 (pginas 282
90).
eat(int amount);
sleep(int hours);
Un mtodo abstracto debe ser declarado en una clase abstracta. Una clase abstracta se
denota utilizando el modificador abstract:
public abstract class className {
. . .
}
No se puede crear ninguna instancia de una clase abstracta. Si una subclase de una clase
abstracta no implementa todos los mtodos abstractos heredados de su padre, la subclase
debe ser definida tambin como abstracta. Una clase abstracta tiene un propsito: actuar
como la superclase de una jerarqua de clases.
Considera una compaa qumica que transporta sus productos en dos tipos de
contenedores: vagones (wagon) y tanques (tank):
/**
* Esta clase modela un contenedor
*
* @author
* @version 1.0.0
*/
public abstract class Container {
/**
* Calcula el volumen de este contenedor.
*
* @return el volumen de este contenedor.
*/
public abstract double computeVolume();
}
Listado 1 Container.java
En la lnea 7, la clase Container es declarada utilizando el modificador abstract. En la
lnea 14, el mtodo computeVolume se declara utilizando el modificador abstract.
La clase Wagon extiende la clase Container, aadiendo los atributos width(ancho),
height(altura) y length(longitud) y proporcionando una implementacin del mtodo
computeVolume:
1: /**
2: * Esta clase modela un contenedor tipo vagn.
3: *
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
* @author
* @version 1.0.0
* @see Container
*/
public class Wagon
extends
Container
Listado 2 Wagon.java
La clase Tank hereda de la clase Container, aadiendo los atributos length(longitud) y
radius(radio) y proporcionando una implementacin del mtodo computeVolume:
1:
2:
3:
4:
5:
6:
/**
* Esta clase modela un contenedor de tipo tanque.
*
* @author
* @version 1.0.0
* @see Container
7: */
8: public class Tank extends Container {
9:
10:
/* El radio del tanque */
11:
private double radius;
12:
13:
/* La longitud del tanque */
14:
private double length;
15:
16:
/**
17:
* Construye un objeto <code>Tank</code>
18:
*
19:
* @param initialRadius el radio de este tanque.
20:
* @param initialLength la longitud de este tanque.
21:
*/
22:
public Tank(double initialRadius,
23:
double initialLength) {
24:
25:
this.radius = initialRadius;
26:
this.length = initialLength;
27:
}
28:
29:
/**
30:
* Sobrescribe {@link Container#computeVolume()}.
31:
* <p>
32:
* Calcula el volumen de este tanque.
33:
* </p>
34:
*
35:
* @return el volumen de este tanque.
36:
*/
37:
public double computeVolume() {
38:
39:
return Math.PI * this.radius * this.radius * this.length;
40:
}
41: }
Listado 3 Tank.java
Las clases que no son abstractas son llamadas clases concretas. Wagon y Tank son clases
concretas.
Una clase abstracta no tiene que tener mtodos abstractos. Sin embargo, dicha clase no
puede ser instanciada porque est definida como abstracta. En el diseo de algunas
jerarquas de clases, slo las subclases pueden ser instanciadas; la superclase se define
como abstracta por lo que no puede ser instanciada.
Por ejemplo, considera la siguiente jerarqua de clase en un sistema de negocios:
/**
* Esta clase modela una persona.
*
* @author
* @version 1.0.0
*/
public abstract class Person {
/* El nombre de la persona */
private String name;
/**
* Construye un objeto <code>Person</code>.
*
* @param initialName el nombre de esta persona.
*/
public Person(String initialName) {
this.name = initialName;
}
/**
* Obtiene el nombre de esta persona.
*
* @return el nombre de esta persona.
*/
public String getName() {
return this.name;
}
31: }
Listado 4 Person.java
A continuacin se presenta una implementacin de la clase Employee:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
/**
* Esta clase modela un empleado.
*
* @author
* @version 1.0.0
* @see Person
*/
public class Employee extends Person
Listado 5 Employee.java
A continuacin se presenta una implementacin de la clase Client:
1:
2:
3:
4:
5:
6:
7:
8:
/**
* Esta clase modela un cliente.
*
* @author
* @version 1.0.0
* @see Person
*/
public class Client extends Person
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36: }
Listado 6 Client.java
No se pueden crear instancias de la clase Person porque la clase Person es abstracta. Por
consecuencia, la siguiente declaracin es ilegal:
Person person = new Person("John");
// ilegal
Sin embargo, pueden crearse instancias de las clases Employee y Client porque son clases
concretas:
Employee employee = new Employee("John", 21);
Client client = new Client("Mary", 6000.0);
2.3.2 Polimorfismo
Lecturas:
Requerida:
o Barker, primera edicin, captulo 7 (pginas 1648).
o Barker, segunda edicin, captulo 7 (pginas 274
80).
Secuencia: Lee el libro de texto antes de leer esta pgina.
En Java, una variable de referencia puede guardar una referencia a un objeto del tipo
declarado o de cualquier subtipo del tipo declarado. Recuerda la clase Container
introducida en la pgina Clases Abstractas:
Esta caracterstica de una variable de referencia ser capaz de hacer referencia a objetos
de diferentes claseshace posible el polimorfismo. El polimorfismo permite asociar el
nombre de un mtodo con muchas implementaciones. Cuando un mtodo polimrfico es
llamado, la Mquina Virtual de Java (JVM) determina qu versin del mtodo ejecutar
examinando la variable de referencia utilizada en el mtodo que hace la llamada. Por
ejemplo, la instruccin
import
java.io.*;
/**
* Esta clase demuestra el uso de las clases contenedor.
*
* @author
* @version 1.0.0
* @see Container
* @see Wagon
* @see Tank
*/
public class ContainerDemo {
private static PrintWriter stdOut =
new PrintWriter(System.out, true);
/**
* Demuestra el uso de polimorfismo en las clases
* contenedor.
*
* @param args no utilizado.
*/
public static void main(String[] args) {
Container container;
container = new Wagon(1, 1, 3);
stdOut.println("Volume: " + container.computeVolume());
container = new Tank(1, 3);
stdOut.println("Volume: " + container.computeVolume());
}
}
Listado1 ContainerDemo.java
La siguiente figura muestra la salida de la clase ContainerDemo:
2.3.3 Interfaces
Interfaces
Representacin UML de Interfaces
Usando Interfaces
Comparando Clases Abstractas e Interfases
Lecturas:
Requerida:
o Barker, primera edicin, captulo 7 (pginas 1758).
o Barker, segunda edicin, captulo 7 (pginas 290
304).
Interfaces
En Java, una interfaz define un conjunto de mtodos abstractos; algunas interfaces incluyen
tambin declaraciones de constantes. Una interfaz se declara casi igual que una clase,
utilizando la palabra clave interface en vez de la palabra clave class:
1: public interface MyInterface {
2:
3:
int CONSTANT = 10;
4:
5:
void methodOne();
6:
7:
double methodTwo();
8:
9:
void methodThree(double value);
10: }
Todos los mtodos que se encuentran en una interfaz son implcitamente pblicos y
abstractos. Como una cuestin de estilo, no se utilizan los modificadores public y
abstract en la definicin de una interfaz.
Todos los campos de datos de una interfaz son implcitamente pblicos, estticos y
finales. Como un aspecto de estilo, no se utilizan los modificadores public, static
y final en la definicin de una interfaz.
Para que una clase haga uso de una interfaz, se utiliza la palabra clave implements, seguida
por el nombre de la interfaz:
Usando Interfaces
La interfaz Device especifica dos comportamientos, turn-off (apagado) y turn-on
(encendido), que son comunes para dispositivos elctricos como focos y televisiones:
/**
* Esta interfaz especifica dos comportamientos, encendido y apagado,
* que son comunes para muchos dispositivos elctricos.
*
* @author
* @version 1.0.0
*/
public interface Device {
/**
* Apaga el dispositivo.
*/
void turnOff();
/**
* Enciende el dispositivo.
*/
void turnOn();
}
Listado 6 Device.java
Todas las clases que implementan la interfaz Device deben implementar los mtodos
turnOff y turnOn. La siguiente clase, DeviceDemo, implementa la interfaz Device. La
clase DeviceDemo tiene un atributo, el nombre del dispositivo. Los mtodos turnOff y
turnOn de la clase DeviceDemo despliegan un mensaje en la salida estndar.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
import java.io.*;
/**
* Esta clase demuestra el uso de la interfaz {@link Device}.
*
* @author
* @version 1.0.0
* @see Device
*/
public class DeviceDemo implements Device {
/* Flujo de salida estndar */
private static PrintWriter stdOut =
new PrintWriter(System.out, true);
/* El nombre del dispositivo */
private String name;
/**
* Prueba la clase <code>DeviceDemo</code>.
*/
public static void main (String[] args) {
Device device = new DeviceDemo("demo");
device.turnOn();
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55: }
device.turnOff();
}
/**
* Construye un objeto <code>DeviceDemo</code>.
*
* @param name el nombre de este dispositivo.
*/
public DeviceDemo (String initialName) {
name = initialName;
}
/**
* Apaga el dispositivo.
*/
public void turnOff() {
stdOut.println("Turn off device " + name);
}
/**
* Enciende el dispositivo.
*/
public void turnOn() {
stdOut.println("Turn on device " + name);
}
Listado 7 DeviceDemo.java
La siguiente figura muestra la salida de la clase DeviceDemo:
import java.io.*;
/**
* Esta clase modela un cronmetro que puede ser iniciado y detenido a
voluntad
* durante un tiempo exacto.
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
*
* @author
* @version 1.0.0
* @see Device
* @see System
*/
public class Stopwatch
implements Device {
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
if (state == Stopwatch.OFF) {
stdOut.println("The device is off");
} else {
long rightNow
= System.currentTimeMillis();
Listado 8 Stopwatch.java
La siguiente figura muestra la salida de la clase Stopwatch.
Una clase abstracta puede definir variables de instancia, mientras que una interfaz
no puede hacerlo.
Una clase abstracta puede implementar mtodos, mientras que una interfaz no puede
hacerlo.
Las interfaces no contienen constructores.
Si una clase hereda de una clase abstracta, sta no puede heredar de otra clase; si
una clase implementa una interfaz, tiene la libertad de heredar de otra clase e
implementar muchas otras interfaces.
Una clase abstracta debe ser utilizada cuando algunos detalles en la implementacin, como
las variables y definiciones de mtodos, son comunes para todas las clases en una jerarqua.
En tal caso, la clase abstracta sera la raz de la jerarqua de clase.
Una interfaz debe ser utilizada para definir un comportamiento que debe ser implementado
por clases de diferentes jerarquas. Las interfaces son el medio por el cual las clases que no
estn relacionadas pueden hacer uso del poder del polimorfismo debido a que una
interfazcomo una clasedefine un tipo. Esto hace posible que las clases pertenecientes a
diferentes jerarquas sean tratadas como instancias del mismo tipo.
Opcional:
o James W. Cooper, The Design Patterns Java
Companion. "Some Background on Design Patterns"
("Antecedentes sobre Patrones de Diseo") (pginas
106).
Los patrones de diseo describen soluciones prcticas para problemas comunes de diseo
que ocurren repetidamente en el desarrollo de software. Un patrn de diseo consta de:
Los patrones de diseo documentan las buenas soluciones de diseo que pueden ser
utilizadas para problemas similares y forman un vocabulario compartido para las
discusiones de solucin de problemas. Adems, los patrones de diseo son una buena
ilustracin de los conceptos orientados a objetos.
Los patrones de diseo fueron popularizados por el libro Design Patterns: Elements of
Reusable Object-Oriented Software (Patrones de Diseo: Elementos de Software
Orientado a Objetos Reutilizable) de Erich Gamma, Richard Helm, Ralph Johnson y John
Vlissides. Este libro cubre 23 patrones, agrupados en tres categoras:
(Creational)
Patrones de Creacin:
(Structural)
Patrones Estructurales:
Abstract Factory
Builder
Factory Method
Prototype
Singleton
Adapter
Bridge
Composite
Decorator
Faade
Flyweight
Proxy
(Behavioral)
Patrones de Comportamiento:
Chain of Responsibility
Command
Iterator
Mediator
Memento
Observer
State
Strategy
Visitor
Interpreter
Template Method
Descripcin
Estructura
Ejemplo
Consecuencias
Lecturas:
Opcional:
o James W. Cooper, The Design Patterns Java
Companion. "The Singleton Pattern" ("El Patrn de
diseo Singular") (pginas 316).
Descripcin
En algunas aplicaciones, hay clases que deben ser instanciadas una sola vez. Por ejemplo,
un sistema operativo debe tener solo un sistema de reloj y una compaa debe tener solo un
sistema contable. El patrn de diseo Singular (Singleton) asegura que se cree slo una
instancia de la clase y provee un mtodo para acceder esa nica instancia. Todos los objetos
que utilizan una instancia de una clase Singular utilizan la misma instancia.
Estructura
Ejemplo
/**
* Esta clase es un singleton que contiene la informacin de
* contacto de <cite>iCarnegie</cite>.
*
* @author
* @version 1.0.0
*/
public class ICarnegieInfo {
static private ICarnegieInfo singletonInstance = null;
private String name;
private String address;
private String telephone;
/*
* Inicializa las variables de instancia. El constructor es
* declarado como privado de modo que slo pueda ser llamado por
mtodos
* de esta clase. Esto previene que otras clases creen ms
* instancias.
*/
private ICarnegieInfo () {
name = "iCarnegie, Inc";
address = "4615 Forbes Avenue Pittsburgh, PA 15213-3796";
telephone = "1.412.622.2150
begin_of_the_skype_highlighting
1.412.622.2150
end_
of_the_skype_highlighting";
}
/**
* Obtiene la nica instancia de la clase
* <code>ICarnegieInfo</code>
*
* @return la nica instancia de la clase
*
<code>ICarnegieInfo</code>
*/
static public ICarnegieInfo getSingletonInstance() {
if (singletonInstance == null) {
singletonInstance = new ICarnegieInfo();
}
return singletonInstance;
}
/**
* Obtiene el nombre de <cite>iCarnegie</cite>
*
* @return un string con el nombre de <cite>iCarnegie</cite>
*/
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
Listado 1 ICarnegieInfo.java
En la lnea 10, la variable esttica y privada singletonInstance es inicializada con una
instancia de la clase ICarnegieInfosingletonInstance ser la nica instancia de la
clase ICarnegieInfo en una aplicacin. En la lnea 22, el constructor es definido como
privado, de modo que otras clases no puedan crear instancias de ICarnegieInfo. En la
lnea 36, la clase define un mtodo esttico llamado getSingletonInstance que regresa
una referencia a la nica instancia de ICarnegieInfo. La primera llamada al mtodo
getSingletonInstance crea la nica instancia.
La siguiente clase demuestra el uso de la clase Singular ICarnegieInfo:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
import
java.io.*;
/**
* Esta clase demuestra el uso de la clase {@link ICarnegieInfo}.
*
* @author
* @version 1.0.0
* @see ICarnegieInfo
*/
public class ICarnegieInfoDemo {
private static PrintWriter stdOut =
new PrintWriter(System.out, true);
/**
* Demuestra el uso de la clase {@link ICarnegieInfo}.
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29: }
*
* @param args no utilizado
*/
public static void main(String[]
args)
ICarnegieInfo companyInfo =
ICarnegieInfo.getSingletonInstance();
stdOut.println("Name:
" + companyInfo.getName());
stdOut.println("Address:
" + companyInfo.getAddress());
stdOut.println("Telephone: " + companyInfo.getTelephone());
}
Listado 2 ICarnegieInfoDemo.java
En las lneas 22 y 23, la aplicacin obtiene la nica instancia llamando al mtodo esttico
ICarnegieInfo.getSingletonInstance.
Consecuencias
El patrn de diseo Singular tiene los siguientes beneficios:
Una clase Singular puede controlar cmo y cuando el cdigo cliente puede acceder
a la nica instancia. El cdigo cliente no tiene la libertad de utilizar el operador new
para crear una instancia de la clase Singular. En vez de eso, debe llamar a un
mtodo esttico que regresa una referencia a la instancia nica.
Una clase Singular puede ser modificada fcilmente si los requerimientos cambian y
la aplicacin necesita limitar el nmero de instancias a un nmero diferente de uno.
Introduccin
Descripcin
Diagrama de Clase UML
Ejemplo
La Interfaz BorrowersFormatter
La Clase PlainTextBorrowersFormatter
La Clase HTMLBorrowersFormatter
La Clase XMLBorrowersFormatter
La Clase LibrarySystem
El Sistema Completo
Lecturas:
Opcional:
o James W. Cooper, The Design Patterns Java
Companion. "The Strategy Pattern" ("El Patrn de
Diseo Estrategia (Strategy)") (pginas 194201).
Introduccin
El patrn de diseo Estrategia (Strategy) es ms difcil de entender que el patrn de diseo
Singular (Singleton) porque utiliza interfaces y polimorfismo. Empezaremos nuestra
discusin con un ejemplo simple. Una vez que tengas la idea bsica, te presentaremos una
descripcin ms formal.
Considera un sistema de comercio electrnico que soporta ventas en Estados Unidos,
Mxico y Canad. En un futuro cercano, la base de clientes ser expandida para incluir
pases de Sudamrica. El sistema debe saber cmo calcular el impuesto de la venta para los
clientes de los tres pases, cada uno de los cuales tiene sus propias reglas para calcular el
impuesto de la venta. El diseo del cdigo para calcular el impuesto de la venta debe ser
flexible, de modo que resulte fcil agregar otros pases. Una solucin es usar un mtodo
monoltico llamado calculateTax, que calcula el impuesto de las ventas para cada pas.
Este mtodo sera parte de la clase que modela una orden.
1: public class Order {
2:
3:
/**
4:
* Calcula el impuesto de una orden.
5:
*
6:
* @param country
El pas que cobrar el impuesto de la orden.
7:
* @param amount
El costo de la orden.
8:
* @return la cantidad de impuesto
9:
*/
10:
private double calculateTax(String country, double amount) {
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32: }
double tax
if (country.equals("United States")) {
tax = ... ;
} else if (country.equals("Canada")) {
tax = ... ;
} else if (country.equals("Mexico")) {
tax = ... ;
}
...
return tax;
}
Si las reglas para calcular el impuesto de las ventas son complejas, el mtodo
calculateTax ser largo y complejo.
La clase contiene el cdigo que utiliza calculateTax y el cdigo que implementa
calculateTax.
Una solucin que utiliza el patrn de diseo Estrategia no tiene dichas desventajas. En una
solucin basada en el patrn de diseo Estrategia, el cdigo para calcular el impuesto de las
ventas en Estados Unidos es encapsulado en su propia clase, al igual que el cdigo para
Canad y Mxico. Cada clase implementa su propia versin del mtodo calculateTax. La
relacin lgica entre las tres clases es expresada en el siguiente diagrama de clase:
Descripcin
En esta pgina, examinaremos una forma de implementar el patrn de diseo Estrategia. El
libro Design Patterns (Patrones de Diseo) describe el patrn de diseo Estrategia con las
siguientes palabras:
"Define una familia de algoritmos, encapsula cada una y las vuelve intercambiables. El
patrn de diseo Estrategia permite que el algoritmo vare independientemente de los
clientes que lo utilizan."
En el patrn de diseo Estrategia, cada algoritmo es encapsulado en su propia clase. Se crea
una interfaz que declara un mtodo para ejecutar un algoritmo y las clases del algoritmo
implementan la interfaz. En consecuencia, cada clase algoritmo tiene su propia versin del
mtodo. Cuando surge la necesidad de un algoritmo en particular, es llamada la versin del
mtodo asociado con dicho algoritmo.
Las aplicaciones donde el patrn de diseo Estrategia puede resultar til son:
Una aplicacin para comprimir archivos que permite al usuario seleccionar el tipo
de compresin
Una aplicacin donde la naturaleza de los datos que sern ordenados determina el
algoritmo de ordenamiento
La interfaz Strategy define la firma del mtodo que ser utilizado para llamar a un
algoritmo.
Las clases ConcreteStrategyX implementan el mtodo declarado en la interfaz
Strategy.
La clase Context mantiene una referencia a un objeto de tipo Strategy, llamada
strategy.
La clase Context contiene el mtodo setStrategy, que permite al cdigo cliente
especificar el algoritmo deseado. setStrategy toma un parmetro de entrada de
tipo Strategy de modo que el cdigo cliente debe pasarlo como una instancia de la
clase ConcreteStrategy asociado con el algoritmo deseado. setStrategy
actualiza la variable de referencia strategy.
La clase Context contiene el mtodo invokeStrategy, el cual es llamado por el
cdigo cliente cuando necesita ejecutar un algoritmo. El algoritmo utilizado est
determinando por la variable de referencia strategy, la cual hace referencia a una
instancia de la clase ConcreteStrategy.
El ejemplo que presentaremos en esta pgina es inusual debido a que la clase contendr el
cdigo cliente.
Ejemplo
El siguiente diagrama de clase muestra una mejora al sistema de la biblioteca. Esta mejora
hace posible dar formato a la informacin de la base de datos de usuarios en una de las
siguientes tres formas: texto plano, HTML y XML:
La Interfaz BorrowersFormatter
A continuacin se presenta una implementacin de la interfaz BorrowersFormatter:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
/**
* Esta interfaz define un mtodo que obtiene una representacin
* string de un objeto {@link BorrowerDatabase}.
*
* @author
* @version 1.0.0
* @see BorrowerDatabase
*/
public interface BorrowersFormatter {
/**
* Obtiene la representacin string de la base de datos de
usuarios
* especificada.
*
* @param borrowerDB la base de datos de usuarios.
* @return la representacin string del objeto
*
{@link BorrowerDatabase} especificado.
*/
String formatBorrowers (BorrowerDatabase borrowerDB);
}
Listado 2 BorrowersFormatter.java
La Clase PlainTextBorrowersFormatter
A
continuacin
se
import java.util.*;
/**
* Esta clase implementa un mtodo que obtiene una representacin en
* texto plano de un objeto{@link BorrowerDatabase}.
*
* @author
* @version 1.0.0
* @see BorrowersFormatter
* @see BorrowerDatabase
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
* @see Borrower
* @see BorrowedItems
* @see CatalogItem
*/
public class PlainTextBorrowersFormatter
implements BorrowersFormatter {
/* Separador de lnea*/
private final static String NEW_LINE =
System.getProperty("line.separator");
/* nica instancia de esta clase */
static private PlainTextBorrowersFormatter singletonInstance =
null;
/**
* Obtiene la nica instancia de la clase
* <code>PlainTextBorrowersFormatter</code>
*
* @return la nica instancia de la clase
*
<code>PlainTextBorrowersFormatter</code>
*/
static public PlainTextBorrowersFormatter getSingletonInstance() {
if (singletonInstance == null) {
singletonInstance = new PlainTextBorrowersFormatter();
}
return singletonInstance;
}
/*
* El constructor se declara como privado de modo que otras clases
no
* puedan crear una instancia de esta clase.
*/
private PlainTextBorrowersFormatter() {
}
/**
* Obtiene una representacin en texto plano de la base de datos
de usuarios
* especificada.
*
* @param borrowerDB la base de datos de usuarios.
* @return una representacin en texto plano de un objeto
*
{@link BorrowerDatabase} especificado.
*/
public String formatBorrowers (BorrowerDatabase borrowerDB) {
String out = "Borrower Database" + NEW_LINE;
for (Borrower borrower : borrowerDB) {
out += borrower.getId() + "_" + borrower.getName();
for (CatalogItem item : borrower.getBorrowedItems()) {
69:
70:
71:
Listado 3 PlainTextBorrowersFormatter.java
La constante NEW_LINE, definida en la lnea 19, contiene el separador de lnea definido por
la propiedad del sistema line.separator. No todas las plataformas utilizan el carcter de
lnea nueva (\n) para terminar lneas. Por ejemplo, los sistemas Windows utilizan "\r\n" y
los sistemas Macintosh utilizan '\r'.
La Clase HTMLBorrowersFormatter
A
continuacin
se
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
import java.util.*;
/**
* Esta clase implementa un mtodo que obtiene una representacin
* HTML de un objeto {@link BorrowerDatabase}.
*
* @author
* @version 1.0.0
* @see BorrowersFormatter
* @see BorrowerDatabase
* @see Borrower
* @see BorrowedItems
* @see CatalogItem
*/
public class HTMLBorrowersFormatter
implements BorrowersFormatter {
/* Separador de lnea */
private final static String NEW_LINE =
System.getProperty("line.separator");
/* nica instancia de esta clase */
static private HTMLBorrowersFormatter singletonInstance = null;
/**
* Obtiene la nica instancia de la clase
* <code>HTMLBorrowersFormatter</code>
*
* @return la nica instancia de la clase
*
<code>HTMLBorrowersFormatter</code>
31:
*/
32:
static public HTMLBorrowersFormatter getSingletonInstance() {
33:
34:
if (singletonInstance == null) {
35:
singletonInstance = new HTMLBorrowersFormatter();
36:
}
37:
38:
return singletonInstance;
39:
}
40:
41:
/*
42:
* El constructor es declarado como privado de modo que otras
43: clases no
44:
* puedan crear una instancia de esta clase.
45:
*/
46:
private HTMLBorrowersFormatter() {
47:
}
48:
49:
/**
50:
* Obtiene una representacin HTML de la base de datos de usuarios
51:
* especificada.
52:
*
53:
* @param borrowerDB la base de datos de usuarios.
54:
* @return una representacin HTML del objeto
55:
*
{@link BorrowerDatabase} especificado.
56:
*/
57:
public String formatBorrowers (BorrowerDatabase borrowerDB) {
58:
59:
String out = "<html>"
60:
+ NEW_LINE
61:
+ " <body>"
62:
+ NEW_LINE + ""
63:
+ "
<center><h2>Borrower
64: Database</h2></center>"
65:
+ NEW_LINE;
66:
67:
for (Borrower borrower : borrowerDB) {
68:
out += "
<hr>"
69:
+ NEW_LINE
70:
+ "
<h4>"
71:
+ borrower.getId()
72:
+ " "
73:
+ borrower.getName()
74:
+ "</h4>"
75:
+ NEW_LINE;
76:
77:
BorrowedItems items = borrower.getBorrowedItems();
78:
79:
if (items.getNumberOfItems() > 0) {
80:
out += "
<blockquote>" + NEW_LINE;
81:
for (CatalogItem item : items) {
82:
out += "
"
83:
+ item.getCode()
84:
+ " "
85:
+ item.getTitle()
86:
+ "<br>"
87:
+ NEW_LINE;
88:
89:
90:
91:
92:
93:
}
out += "
</blockquote>" + NEW_LINE;
}
}
out += "
return out;
}
}
Listado 4 HTMLBorrowersFormatter.java
La Clase XMLBorrowersFormatter
La siguiente es una implementacin de la clase concreta XMLBorrowersFormatter. La
clase XMLBorrowersFormatter es implementada como Singular (Singleton), de modo que
no se crear un nuevo objeto cada vez que se utilice el formato XML:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
import java.util.*;
/**
* Esta clase implementa un mtodo que obtiene una representacin
* de un objeto {@link BorrowerDatabase}.
*
* @author
* @version 1.0.0
* @see BorrowersFormatter
* @see BorrowerDatabase
* @see Borrower
* @see BorrowedItems
* @see CatalogItem
*/
public class XMLBorrowersFormatter
implements BorrowersFormatter {
/* Separador de lnea */
private final static String NEW_LINE =
System.getProperty("line.separator");
/* nica instancia de esta clase */
static private XMLBorrowersFormatter singletonInstance = null;
/**
* Obtiene la nica instancia de la clase
* <code>XMLBorrowersFormatter</code>
*
* @return la nica instancia de la clase
*
<code>XMLBorrowersFormatter</code>
*/
static public XMLBorrowersFormatter getSingletonInstance() {
if (singletonInstance == null) {
singletonInstance = new XMLBorrowersFormatter();
}
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
return singletonInstance;
}
/*
* El constructor se declara como privado de modo que otras
* clases no puedan crear una instancia de esta clase.
*/
private XMLBorrowersFormatter() {
}
/**
* Obtiene una representacin XML de la base de datos de usuarios
* especificada.
*
* @param borrowerDB la base de datos de usuarios.
* @return una representacin XML del objeto
*
{@link BorrowerDatabase} especificado.
*/
public String formatBorrowers (BorrowerDatabase borrowerDB) {
String out = "<BorrowerDatabase>" + NEW_LINE ;
for (Borrower borrower : borrowerDB) {
out += " <Borrower id=\""
+ borrower.getId()
+ "\" name=\""
+ borrower.getName()
+ "\">"
+ NEW_LINE;
BorrowedItems items = borrower.getBorrowedItems();
if (items.getNumberOfItems() > 0) {
out += "
<BorrowedItems>" + NEW_LINE;
for (CatalogItem item : items) {
out += "
<CatalogItem id=\""
+ item.getCode()
+ "\">"
+ item.getTitle()
+ "</CatalogItem>" + NEW_LINE;
}
out += "
</BorrowedItems>" + NEW_LINE;
}
out += "
</Borrower>" + NEW_LINE;
}
out += "</BorrowerDatabase>";
return out;
}
}
Listado 5 XMLBorrowersFormatter.java
La Clase LibrarySystem
A continuacin se presenta una implementacin de la clase LibrarySystem. La clase
LibrarySystem permite al usuario especificar un formato y despus desplegar la
informacin de la base de datos de usuarios en el formato especificado. La clase contiene:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
public static void main(String[] args) throws IOException {
42:
43:
LibrarySystem app = new LibrarySystem();
44:
45:
app.run();
46:
}
47:
48:
/**
49:
* Crea un objeto <code>LibrarySystem</code>.
50:
*/
51:
private LibrarySystem() {
52:
53:
borrowerDB = loadBorrowers(loadCatalog());
54:
borrowersFormatter =
55:
PlainTextBorrowersFormatter.getSingletonInstance();
56:
}
57:
58:
/**
59:
* Carga los datos del catlogo.
60:
*/
61:
private Catalog loadCatalog() {
62:
63:
Catalog catalog = new Catalog();
64:
65:
catalog.addItem(new Book("B001",
66:
"Effective Java Programming", 2001,
67:
"Joshua Bloch", 252));
68:
catalog.addItem(new Book("B002",
69:
"Design Patterns", 1995,
70:
"Erich Gamma et al", 395));
71:
catalog.addItem(new Book("B003",
72:
"Refactoring", 1999,
73:
"Martin Fowler", 431));
74:
catalog.addItem(new Book("B004",
75:
"The Mythical Man-Month", 1995,
76:
"Frederick P. Brooks", 322));
77:
catalog.addItem(new Book("B005",
78:
"Code Complete", 1993,
79:
"Steve C McConnell", 857));
80:
catalog.addItem(new Book("B006",
81:
"The Psychology of Comp. Progr.",
82: 1998,
83:
"Gerald M. Weinberg", 360));
84:
catalog.addItem(new Book("B007",
85:
"Programming Pearls ", 1999,
86:
"Jon Bentley", 239));
87:
catalog.addItem(new Book("B008",
88:
"The Practice of Programming", 1999,
89:
"Brian W. Kernighan", 257));
90:
catalog.addItem(new Book("B009",
91:
"Peopleware", 1999,
92:
"Tom Demarco", 245));
93:
catalog.addItem(new Book("B010",
94:
"The Java Programming Language",
95: 2000,
96:
"Ken Arnold", 595));
97:
catalog.addItem(new Book("B011",
98:
"Core J2EE Patterns", 2001,
99:
"Deepak Alur", 496));
100:
catalog.addItem(new Book("B012",
101:
"Rapid Development", 1996,
102:
"Steve C McConnell", 680));
103:
catalog.addItem(new Book("B013",
104:
"Applying UML and Patterns", 2001,
105:
"Craig Larman", 656));
106:
catalog.addItem(new Book("B014",
107:
"The Little Schemer", 1995,
108:
"Daniel P. Friedman", 216));
109:
catalog.addItem(new Book("B015",
110:
"Agile Software Development", 2001,
111:
"Alistair Cockburn", 256));
112:
catalog.addItem(new Recording("R001",
113:
"Getz/Gilberto", 1963,
114:
"Stan Getz and Joao Gilberto",
115: "CD"));
116:
catalog.addItem(new Recording("R002",
117:
"Kind of Blue", 1997,
118:
"Miles Davis", "CD"));
119:
catalog.addItem(new Recording("R003",
120:
"Supernatural", 1999,
121: "Santana",
122:
"Tape"));
123:
catalog.addItem(new Recording("R004",
124:
"Private Collection", 1983,
125:
"Jon & Vangelis", "Tape"));
126:
catalog.addItem(new Recording("R005",
127:
"Abbey Road", 1969,
128:
"Beatles", "CD"));
129:
catalog.addItem(new Recording("R006",
130:
"Joshua Tree", 1990,
131:
"U2", "CD"));
132:
133:
return catalog;
134:
}
135:
136:
/**
137:
* Carga una base de datos de usuarios.
138:
*/
139:
private BorrowerDatabase loadBorrowers(Catalog catalog) {
140:
141:
BorrowerDatabase borrowerDB = new BorrowerDatabase();
142:
143:
Borrower borrower = new Borrower("ID001", "James Addy");
144:
145:
borrower.getBorrowedItems().addItem(
146:
catalog.getItem("B003"));
147:
borrower.getBorrowedItems().addItem(
148:
catalog.getItem("R001"));
149:
borrower.getBorrowedItems().addItem(
150:
catalog.getItem("B012"));
151:
borrowerDB.addBorrower(borrower);
152:
153:
borrower = new Borrower("ID002", "John Doust");
154:
borrowerDB.addBorrower(borrower);
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
choice = getChoice();
while (choice != 0)
if (choice == 1) {
setBorrowersFormatter(
212: PlainTextBorrowersFormatter.getSingletonInstance());
213:
} else if (choice == 2) {
214:
setBorrowersFormatter(
215:
HTMLBorrowersFormatter.getSingletonInstance());
216:
} else if (choice == 3) {
217:
setBorrowersFormatter(
218:
XMLBorrowersFormatter.getSingletonInstance());
219:
}
220:
displayBorrowers();
221:
222:
choice = getChoice();
223:
}
224:
}
225:
226:
/**
227:
* Despliega un men de opciones y verifica la opcin.
228:
*
229:
* @return un entero dentro del rango [0,3]
230:
*/
231:
private int getChoice() throws IOException {
232:
233:
int input;
234:
235:
do {
236:
try {
237:
stdErr.println();
238:
stdErr.print("[0] Quit\n"
239:
+ "[1] Display Plain Text\n"
240:
+ "[2] Display HTML\n"
241:
+ "[3] Display XML\n"
242:
+ "choice> ");
243:
stdErr.flush();
244:
245:
input = Integer.parseInt(stdIn.readLine());
246:
247:
stdErr.println();
248:
249:
if (0 <= input && 3 >= input) {
250:
break;
251:
} else {
252:
stdErr.println("Invalid choice: " + input);
253:
}
254:
} catch (NumberFormatException nfe) {
255:
stdErr.println(nfe);
256:
}
257:
} while (true);
258:
259:
return input;
260:
}
261:
262:
/**
263:
* Cambia el formato en el cual la base de datos de usuarios ser
264:
* desplegada.
265:
*
266:
* @param newFormatter formato en el cual la base de datos de
267: usuarios ser
268:
*
desplegada.
269:
270:
271:
272:
273:
274:
275:
276:
277:
*/
private void setBorrowersFormatter(
BorrowersFormatter newFormatter) {
borrowersFormatter = newFormatter;
}
/**
* Despliega los usuarios en el formato actual.
*/
private void displayBorrowers() {
stdOut.println(
borrowersFormatter.formatBorrowers(borrowerDB));
}
}
Listado 6 LibrarySystem.java
En las lneas 204 a 214, la aplicacin responde a la entrada del usuario. Los mtodos
setBorrowersFormatter y displayBorrowers son llamados uno despus de otro. Esto
no ocurre necesariamente. Considera una interfaz grfica de usuario (GUI) para el sistema
de la biblioteca que contiene botones de radio para especificar el formato y un botn para
especificar la base de datos de usuarios en el formato especificado. Cuando el usuario
selecciona un botn de radio, la clase GUI debe llamar a setBorrowersFormatter.
Posteriormente, cuando el usuario hace clic en el botn de Desplegar, la clase GUI debe
llamar a displayBorrowers.
Referencias
Shalloway, Alan and James R. Trott. Design Patterns Explained: A New Perspective on
Object-Oriented Design. Addison-Wesley Publishing Co., 2001.
Requerido:
o Barker, primera edicin, captulo 15 (pginas 427
32).
o Barker, segunda edicin, captulo 15 (pginas 624
630).
Secuencia: Lee el libro de texto antes de leer esta pgina.
abarcar otros objetos de E/S, incluyendo aquellos utilizados para E/S con archivos. En este
curso, las clases que necesitan E/S con archivos emplearn las siguientes declaraciones:
1: BufferedReader fileIn =
2:
new BufferedReader(new FileReader(filename));
3:
4: PrintWriter fileOut =
5:
new PrintWriter(new FileWriter(filename));
6:
7: PrintWriter fileAppend =
8:
new PrintWriter(new FileWriter(filename, true);
4:
5:
6:
7: }
// procesa la lnea
line = fileIn.readLine();
// escribiendo en un archivo
fileOut.println(5);
// escribiendo en la consola
stdOut.println(5);
BufferedReader fileIn =
new BufferedReader(new FileReader(filename));
PrintWriter fileOut =
new PrintWriter(new FileWriter(filename));
...
fileIn.close();
fileOut.close();
import
java.io.*;
/**
* Hace una copia de un archivo.
*
* @author
* @version 1.0.0
*/
public class CopyFile {
/* Flujo de entrada estndar */
private static BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
/* Flujo de salida estndar */
private static PrintWriter stdOut =
new PrintWriter(System.out, true);
/* Flujo de error estndar */
private static PrintWriter stdErr =
new PrintWriter(System.err, true);
/**
* Hace una copia de un archivo.
*
* @param args no utilizado.
* @throws IOException Si ocurre un error de E/S.
*/
public static void main(String[] args) throws IOException
stdErr.print("Source filename:
stdErr.flush();
");
BufferedReader input =
new BufferedReader( new FileReader(stdIn.readLine()));
stdErr.print("Destination filename:
stdErr.flush();
");
PrintWriter output =
new PrintWriter(new FileWriter(stdIn.readLine()));
String
line = input.readLine();
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55: }
Listado 7 CopyFile.java
En las lneas 34 y 40, se abren los archivos de entrada y salida. El cdigo de la lnea 43 a la
lnea 48 lee una lnea del archivo de entrada y escribe esa misma lnea en el archivo de
salida. Cuando se llega al final del archivo, el valor de la variable line toma un valor de
null y entonces la condicin no se cumple y se termina el bucle while. En las lneas 50 y
51, se cierran los archivos.
En esta pgina te presentamos una versin del sistema de biblioteca que incorpora E/S con
archivos. En esta versin:
1. Los datos del catlogo de la biblioteca no estarn inmersos en la codificacin de la
aplicacin. En vez de eso, el catlogo estar almacenado en un archivo de datos y el
sistema cargar el catlogo de dicho archivo.
2. El sistema ser capaz de guardar la informacin de los usuarios de la biblioteca en un
archivo, utilizando alguno de los siguientes tres formatos: Texto plano, HTML y XML.
Donde:
Los campos estn delimitados por un guin bajo ( _ ). Los campos en s no contienen
guiones bajos.
Las lneas con la informacin de las grabaciones tienen el siguiente formato:
Recording_code_title_year_performer_format
Donde:
Los campos estn delimitados por un guin bajo ( _ ). Los campos en s no contienen
guiones bajos.
El siguiente archivo contiene el catlogo de una biblioteca en el formato descrito
anteriormente:
El siguiente diagrama de clase resalta los elementos utilizados para implementar esta
versin del sistema de biblioteca:
Mtodo:
import java.io.*;
/**
* Esta interfaz declara un mtodo para obtener un catlogo de
biblioteca
* de un archivo.
*
* @author
* @version 1.1.0
* @see Catalog
*/
public interface LibraryCatalogLoader {
/**
* Carga la informacin en el archivo especificado en un catlogo
* de biblioteca y regresa el catlogo.
*
* @param filename el nombre del archivo que contiene
*
los datos del catlogo.
* @return un {@link Catalog} con los datos indicados en el
archivo.
* @throws IOException si hay un error al leer la informacin del
*
archivo en el archivo especificado.
* @throws FileNotFoundException si el archivo especificado no
*
existe.
* @throws DataFormatException si el archivo contiene datos mal
*
formados.
*/
Catalog loadCatalog(String filename) throws IOException,
FileNotFoundException, DataFormatException;
}
Listado 1 LibraryCatalogLoader.java
Clase FileLibraryCatalogLoader
Mtodos:
Este mtodo utiliza la clase StringTokenizer para extraer los datos del libro de la
lnea especificada. Si la lnea no tiene ningn error, este mtodo regresa un objeto
Book que encapsula los datos del libro. Si la lnea tiene errores, es decir, si no tiene
el nmero de tokens esperado o los tokens que deberan contener un entero no lo
tienen, este mtodo lanza una excepcin DataFormatException que contiene la lnea
con los datos mal formados.
Este mtodo usa la clase StringTokenizer para extraer los datos de la grabacin
de la lnea especificada. Si la lnea no tiene ningn error, este mtodo regresa un
objeto Recording que encapsula los datos de la grabacin. Si la lnea tiene errores,
es decir, si no tiene el nmero de tokens esperado o los tokens que deberan
contener un entero no lo tienen, este mtodo lanza una excepcin
DataFormatException que contiene la lnea con los datos mal formados.
A continuacin se presenta la implementacin de la clase FileLibraryCatalogLoader:
1:
2:
3:
4:
5:
6:
7:
8:
9:
import java.util.*;
import java.io.*;
/**
* Crea un catlogo de biblioteca y lo carga con los datos
almacenados
* en un archivo.
*
* @author
* @version 1.0.0
* @see LibraryCatalogLoader
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
* @see Catalog
* @see CatalogItem
* @see Recording
* @see Book
*/
public class FileLibraryCatalogLoader implements LibraryCatalogLoader
{
/* Prefijo de una lnea con datos de libros */
private final static String BOOK_PREFIX = "Book";
/* Prefijo de una lnea de datos de grabaciones */
private final static String RECORDING_PREFIX = "Recording";
/* Delimitador */
private final static String DELIM = "_";
/**
* Carga la informacin del archivo especificado en un catlogo
de
* biblioteca y regresa el catlogo.
*
* @param filename El nombre de un archivo que contiene
informacin
*
del catlogo.
* @return un {@link Catalog} con los datos indicados en el
archivo.
* @throws IOException si hay algn error al leer la
*
informacin del archivo especificado.
* @throws FileNotFoundException si el archivo especificado no
*
existe.
* @throws DataFormatException si el archivo contiene datos mal
*
formados.
*/
public Catalog loadCatalog (String filename) throws IOException,
FileNotFoundException, DataFormatException {
Catalog catalog = new Catalog();
BufferedReader reader =
new BufferedReader(new FileReader(filename));
String line = reader.readLine();
while (line != null) {
CatalogItem item = null;
if (line.startsWith(BOOK_PREFIX)) {
item = readBook(line);
} else if (line.startsWith(RECORDING_PREFIX)) {
item = readRecording(line);
} else {
throw new DataFormatException(line);
}
catalog.addItem(item);
59:
line = reader.readLine();
}
60:
61:
reader.close();
62:
63:
return catalog;
64:
}
65:
/**
66:
* Extrae los datos del libro del archivo en la lnea
67:
especificada
y regresa
68:
* un objeto {@link Book} que encapsula los datos del libro.
69:
*
70:
* @param line una cadena que contiene datos de libros.
71:
* @return un objeto <code>Book</code> que encapsula los datos
72: del
*
libro en la lnea especificada.
73:
*
@throws
DataFormatException
si la lnea contiene errores.
74:
*/
75:
private Book readBook (String line) throws DataFormatException {
76:
77:
StringTokenizer tokenizer = new StringTokenizer(line, DELIM);
78:
79:
if (tokenizer.countTokens() != 6) {
80:
throw new DataFormatException(line);
81:
} else {
82:
try {
83:
84:
String prefix = tokenizer.nextToken();
85:
return new Book (tokenizer.nextToken(),
86:
tokenizer.nextToken(),
87:
88:
Integer.parseInt(tokenizer.nextToken()),
89:
tokenizer.nextToken(),
90:
91: Integer.parseInt(tokenizer.nextToken()));
92:
} catch (NumberFormatException nfe) {
93:
throw new DataFormatException(line);
94:
}
95:
}
96:
}
97:
98:
/**
99:
* Extrae los datos de la grabacin en la lnea especificada y
100: regresa
* un objeto {@link Recording} que encapsula los datos del libro.
101:
*
102:
* @param line una cadena que contiene datos de la grabacin.
103:
* @return un objeto <code>Recording</code> que encapsula los
104:
*
datos de la grabacin en la lnea especificada.
105:
* @throws DataFormatException si la lnea contiene errores.
*/
106:
private Recording readRecording (String line)
107:
throws DataFormatException {
108:
StringTokenizer tokenizer =
new StringTokenizer(line,
109:
110: DELIM);
111:
if (tokenizer.countTokens() != 6) {
112:
113:
throw new DataFormatException(line);
114:
} else {
try {
115:
116:
String prefix = tokenizer.nextToken();
117:
118:
return new Recording (tokenizer.nextToken(),
119:
tokenizer.nextToken(),
120:
Integer.parseInt(
121:
tokenizer.nextToken()),
tokenizer.nextToken(),
122:
tokenizer.nextToken());
123:
}
catch
(NumberFormatException
nfe) {
124:
125:
throw new DataFormatException(line);
126:
}
127:
}
128:
}
129: }
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
Listado 2 FileLibraryCatalogLoader.java
Clase DataFormatException
Esta excepcin es lanzada cuando una lnea de un archivo que est siendo analizado
contiene errores:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
* se analiza un archivo.
*
* @author
* @version 1.0.0
*/
public class DataFormatException extends Exception
/**
* Construye una excepcin <code>DataFormatException</code> sin
mensaje de
* detalle.
*/
public DataFormatException() {
}
/**
* Construye una excepcin <code>DataFormatException</code> con un
* mensaje de detalle de la excepcin.
*
* @param message los datos mal formados
*/
public DataFormatException(String message) {
super(message);
}
}
Listado 3 DataFormatException.java
import java.io.*;
import java.util.*;
/**
* Esta clase implementa un ejemplo del sistema de biblioteca.
*
* @author
* @version 1.1.0
* @see CatalogItem
* @see Book
* @see Recording
* @see Catalog
* @see Borrower
* @see BorrowerDatabase
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
* @see BorrowersFormatter
* @see PlainTextBorrowersFormatter
* @see HTMLBorrowersFormatter
* @see XMLBorrowersFormatter
* @see LibraryCatalogLoader
* @see FileLibraryCatalogLoader
*/
public class LibrarySystem {
private static BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
private static PrintWriter stdOut =
new PrintWriter(System.out, true);
private static PrintWriter stdErr =
new PrintWriter(System.err, true);
private Catalog
catalog;
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
System.exit(1);
}
LibrarySystem
app.run();
}
}
/*
* Construye un objeto <code>LibrarySystem</code>.
* Inicializa el catlogo y la base de datos del usuario con
* los valores especificados en el parmetro.
*/
private LibrarySystem(Catalog initialCatalog) {
this.catalog = initialCatalog;
this.borrowerDB = loadBorrowers(catalog);
this.borrowersFormatter =
PlainTextBorrowersFormatter.getSingletonInstance();
}
/*
* Carga un objeto BorrowerDatabase.
*/
private BorrowerDatabase loadBorrowers(Catalog catalog) {
BorrowerDatabase borrowerDB = new BorrowerDatabase();
Borrower borrower = new Borrower("ID001", "James Addy");
borrower.getBorrowedItems().addItem(
catalog.getItem("B003"));
borrower.getBorrowedItems().addItem(
catalog.getItem("R001"));
borrower.getBorrowedItems().addItem(
catalog.getItem("B012"));
borrowerDB.addBorrower(borrower);
borrower = new Borrower("ID002", "John Doust");
borrowerDB.addBorrower(borrower);
borrower = new Borrower("ID003", "Constance Foster");
borrower.getBorrowedItems().addItem(
catalog.getItem("B006"));
borrowerDB.addBorrower(borrower);
borrower = new Borrower("ID004", "Harold Gurske");
borrower.getBorrowedItems().addItem(
catalog.getItem("B002"));
borrowerDB.addBorrower(borrower);
borrower = new Borrower("ID005", "Mary A. Rogers");
borrowerDB.addBorrower(borrower);
borrower = new Borrower("ID006", "Laura Novelle");
borrower.getBorrowedItems().addItem(
111:
catalog.getItem("B007"));
borrower.getBorrowedItems().addItem(
112:
catalog.getItem("B009"));
113:
borrowerDB.addBorrower(borrower);
114:
115:
borrower = new Borrower("ID007", "David M. Prescott");
116:
borrower.getBorrowedItems().addItem(
117:
catalog.getItem("B011"));
borrowerDB.addBorrower(borrower);
118:
119:
borrower = new Borrower("ID008", "Francis Matthews");
120:
borrower.getBorrowedItems().addItem(
121:
catalog.getItem("R003"));
122:
borrower.getBorrowedItems().addItem(
123:
catalog.getItem("B005"));
124:
borrowerDB.addBorrower(borrower);
125:
borrower = new Borrower("ID009", "Thomas Ferris");
126:
borrowerDB.addBorrower(borrower);
127:
128:
borrower = new Borrower("ID010", "John Johnson");
129:
borrower.getBorrowedItems().addItem(
130:
catalog.getItem("B004"));
131:
borrowerDB.addBorrower(borrower);
132:
return borrowerDB;
133:
}
134:
135:
/*
136:
* Presenta un men de opciones y ejecuta la tarea seleccionada.
137:
*/
private void run() throws IOException {
138:
139:
int choice = getChoice();
140:
141:
while (choice != 0) {
142:
if (choice == 1) {
143:
displayCatalog();
144:
} else if (choice == 2) {
this.borrowersFormatter =
145:
146:
147: PlainTextBorrowersFormatter.getSingletonInstance();
writeFile(readFileName(),
148:
149: this.borrowersFormatter.formatBorrowers(this.borrowerDB));
150:
} else if (choice == 3) {
151:
this.borrowersFormatter =
HTMLBorrowersFormatter.getSingletonInstance();
152:
writeFile(readFileName(),
153:
154:
this.borrowersFormatter.formatBorrowers(this.borrowerDB));
155:
} else if (choice == 4) {
156:
this.borrowersFormatter =
157:
XMLBorrowersFormatter.getSingletonInstance();
writeFile(readFileName(),
158:
159:
this.borrowersFormatter.formatBorrowers(this.borrowerDB));
160:
}
161:
choice = getChoice();
162:
}
163:
}
164:
165:
/*
166:
* Despliega un men de opciones y verifica la seleccin del
167: usuario.
*/
168:
private
int getChoice() throws IOException {
169:
170:
int input;
171:
172:
do {
173:
try {
stdErr.println();
174:
stdErr.print("[0] Quit\n"
175:
+ "[1] Display catalog\n"
176:
+ "[2] Save borrower database (plain
177:
text)\n"
178:
+ "[3] Save borrower database (HTML)\n"
179:
+ "[4] Save borrower database (XML)\n"
180:
+ "choice> ");
stdErr.flush();
181:
182:
input = Integer.parseInt(stdIn.readLine());
183:
184:
stdErr.println();
185:
186:
if (0 <= input && 4 >= input) {
break;
187:
} else {
188:
stdErr.println("Invalid choice: " + input);
189:
}
190:
} catch (NumberFormatException nfe) {
191:
stdErr.println(nfe);
192:
}
193:
} while (true);
194:
return input;
195:
}
196:
197:
/*
198:
* Despliega el catlogo.
199:
*/
200:
private void displayCatalog() {
201:
int numberOfItems = this.catalog.getNumberOfItems();
202:
203:
if (numberOfItems == 0) {
204:
stdErr.println("The catalog is empty");
205:
} else {
206:
for (CatalogItem item : this.catalog) {
stdOut.println(item.getCode() + " "
207:
+ item.getTitle() + " " +
208:
(item.isAvailable()? "(A)" : "(NA)"));
209:
}
}
210:
}
211:
212:
/*
213:
* Solicita un nombre de archivo (el nombre del archivo que
214:
* almacenar la base de datos de usuarios) y regresa la
215: respuesta.
*/
216:
private String readFileName() throws IOException {
217:
218:
stdErr.print("File name> ");
219:
stdErr.flush();
220:
221:
return stdIn.readLine();
222:
}
223:
/*
224:
* Crea un nuevo archivo (que tiene el nombre especificado) y
225:
escribe
226:
* la cadena especificada en nuevo archivo
227:
*/
228:
private void writeFile(String fileName, String content)
229:
throws IOException {
230:
PrintWriter fileOut =
231:
new PrintWriter(new FileWriter(fileName));
232:
233:
fileOut.println(content);
234:
fileOut.close();
235:
}
236: }
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
Listado 4 LibrarySystem.java
Componente JLabel
Componente JButton
Componente JRadioButton
Componente JTextField
Componente JTextArea
Componente JList
Lecturas:
Requerida:
o Barker, primera edicin, captulo 16 (pginas 471
522).
o Barker, segunda edicin, captulo 16 (pginas 681
735).
Secuencia: Lee el libro de texto antes de leer esta pgina.
Esta pgina muestra cmo se crean y se personalizan los componentes Swing. La pgina
Manejo de Eventos Swing mostrar cmo se manejan los eventos de estos componentes.
Componente JLabel
Los componentes de la clase JLabel pueden desplegar texto, una imagen o ambos. La clase
JLabelDemo crea una ventana con tres componentes JLabel:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
import java.awt.*;
import javax.swing.*;
/**
* Demuestra el componente {@link JLabel}. Esta clase hereda de
* la clase {@link JPanel}.
*
* @author
* @version 1.0.0
*/
public class JLabelDemo extends JPanel {
private JLabel labelLeft;
private JLabel labelCenter;
private JLabel labelRight;
/**
* Crea una ventana.
*
* @param args no utilizado.
*/
public static void main(String[] args) {
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62: }
Listado 1 JLabelDemo.java
La siguiente ventana se despliega al ejecutar JLabelDemo:
La primera etiqueta (label) contiene texto e imagen, la segunda etiqueta contiene texto y la
tercera etiqueta contiene una imagen.
Observa los siguientes aspectos del cdigo:
En
las
lneas
49
setVerticalTextPosition
en relacin a la imagen.
entre el texto y la
imagen.
Componente JButton
Los componentes de la clase JButton pueden desplegar texto, una imagen o ambos. La
clase JButtonDemo crea una ventana con dos componentes JButton:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
import java.awt.*;
import javax.swing.*;
/**
* Demuestra el componente {@link JButton}. Esta clase hereda de
* la clase {@link JPanel}.
*
* @author
* @version 1.0.0
*/
public class JButtonDemo extends JPanel {
private
private
private
private
/**
JButton buttonUp;
JButton buttonDown;
ImageIcon arrowUp;
ImageIcon arrowDown;
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69: }
Listado 2 JButtonDemo.java
La siguiente ventana es desplegada cuando se ejecuta JButtonDemo:
En
las
lneas
51
Componente JRadioButton
Los componentes de la clase JRadioButton pueden ser seleccionados o deseleccionados
por el usuario. Si los componentes JRadioButton son agrupados, por medio de la clase
ButtonGroup, slo puede seleccionarse un botn a la vez. La clase JButtonDemo crea una
ventana con tres componentes JRadioButton y los agrupa:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
import java.awt.*;
import javax.swing.*;
/**
* Demuestra el componente {@link JRadioButton}. Esta clase hereda de
* la clase {@link JPanel}.
*
* @author
* @version 1.0.0
*/
public class JRadioButtonDemo extends JPanel {
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61: }
private JRadioButton
private JRadioButton
private JRadioButton
buttonOne;
buttonTwo;
buttonThree;
/**
* Crea una ventana.
*
* @param args no utilizado.
*/
public static void main(String[] args) {
JFrame frame = new JFrame("JRadioButtonDemo");
frame.setContentPane(new JRadioButtonDemo());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
// Ajusta el tamao de la ventana
frame.setVisible(true);
}
/**
* Crea tres componentes {@link JRadioButton}.
*/
public JRadioButtonDemo() {
setLayout(new GridLayout(1, 3));
setBackground(Color.white);
// Crea los
buttonOne =
buttonTwo =
buttonThree
botones de radio
new JRadioButton("One", true);
new JRadioButton("Two");
= new JRadioButton("Three");
Listado 3 JRadioButtonDemo.java
La siguiente ventana es desplegada al ejecutar JRadioButtonDemo:
boolean isSelected().
Componente JTextField
Los componentes de la clase JTextField permiten al usuario introducir (o editar) una
pequea cantidad de texto. Estos componentes son utilizados tambin para desplegar
pequeas cantidades de texto. La clase JTextFieldDemo crea una ventana con todos
componentes JLabel y componentes JTextField:
1:
2:
3:
4:
5:
6:
7:
8:
9:
import java.awt.*;
import javax.swing.*;
/**
* Demuestra el componente {@link JTextField}. Esta clase hereda de
* la clase {@link JPanel}.
*
* @author
* @version 1.0.0
10: */
11: public class JTextFieldDemo extends JPanel {
12:
13:
private JLabel labelCountry;
14:
private JLabel labelCapital;
15:
private JTextField textFieldCountry;
16:
private JTextField textFieldCapital;
17:
18:
/**
19:
* Crea una ventana.
20:
*
21:
* @param args no utilizado.
22:
*/
23:
public static void main(String[] args) {
24:
25:
JFrame frame = new JFrame("JTextFieldDemo");
26:
27:
frame.setContentPane(new JTextFieldDemo());
28:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
29:
frame.pack();
// Ajusta el tamao de la ventana
30:
frame.setVisible(true);
31:
}
32:
33:
/**
34:
* Crea dos componentes {@link JLabel} y dos componentes
35:
* {@link JTextField}.
36:
*/
37:
public JTextFieldDemo() {
38:
39:
setLayout(new GridLayout(2, 1));
40:
setBackground(Color.white);
41:
42:
// Crea los componentes
43:
labelCountry = new JLabel("Country:");
44:
textFieldCountry = new JTextField("Spain", 10);
45:
labelCapital = new JLabel("Capital:");
46:
textFieldCapital = new JTextField("Madrid", 10);
47:
48:
// Cambia los colores de los campos de texto
49:
textFieldCapital.setBackground(new Color(150, 0, 0));
50:
textFieldCapital.setForeground(Color.white);
51:
52:
// Define la alineacin del texto
53:
textFieldCapital.setHorizontalAlignment(JTextField.CENTER);
54:
55:
// Hace que el rea de texto sea no editable
56:
textFieldCapital.setEditable(false);
57:
58:
// Aade componentes al contenedor.
59:
JPanel panelCountry = new JPanel();
60:
61:
panelCountry.setBackground(Color.white);
62:
panelCountry.add(labelCountry);
63:
panelCountry.add(textFieldCountry);
64:
add(panelCountry);
65:
66:
JPanel panelCapital = new JPanel();
67:
68:
69:
70:
71:
72:
73: }
panelCapital.setBackground(Color.white);
panelCapital.add(labelCapital);
panelCapital.add(textFieldCapital);
add(panelCapital);
}
Listado 4 JTextFieldDemo.java
La siguiente ventana es desplegada cuando se ejecuta JTextFieldDemo:
En la lnea 56, el mtodo setEditable hace que el campo de texto no sea editable.
En las lneas 59 a 71, se crean dos paneles. Se aade una etiqueta y un campo de
texto a cada panel y despus los paneles son agregados al marco. Date cuenta que el
diseo predeterminado de un panel es diseo de flujo. En diseo de flujo, cada
componente asume su tamao preferido.
Componente JTextArea
Los componentes de la clase JTextArea permiten al usuario introducir (o editar) mltiples
lneas de texto. Estos componentes se utilizan tambin para desplegar bloques de texto. Un
componente JTextArea no tiene barras de desplazamiento. Si se requieren barras de
import java.awt.*;
import javax.swing.*;
/**
* Demuestra el componente {@link JTextArea}. Esta clase hereda de
* la clase {@link JPanel}.
*
* @author
* @version 1.0.0
*/
public class JTextAreaDemo extends JPanel {
private JTextArea textAreaOne;
private JTextArea textAreaTwo;
/**
* Crea una ventana.
*
* @param args no utilizado.
*/
public static void main(String[] args) {
JFrame frame = new JFrame("JTextAreaDemo");
frame.setContentPane(new JTextAreaDemo());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
// Ajusta el tamao de la ventana
frame.setVisible(true);
}
/**
* Crea dos componentes {@link JTextArea}.
*/
public JTextAreaDemo() {
setBackground(Color.white);
String text = "Line1\nLine2\nLine3\nLine4\nLine5\n"
+ "Line6\nLine7\nLine8\nLine9\nLine10\n";
// Crea los componentes
textAreaOne = new JTextArea(text, 7, 10);
textAreaTwo = new JTextArea(text, 7, 10);
// Cambia los colores de los componentes
textAreaOne.setBackground(new Color(0, 0, 150));
textAreaTwo.setBackground(new Color(0, 150, 0));
textAreaOne.setForeground(Color.white);
textAreaTwo.setForeground(Color.white);
// Hace que el rea de texto no sea editable
textAreaTwo.setEditable(false);
53:
54:
// Aade componentes de rea de texto al contenedor de la
55: barra de desplazamiento.
56:
add(new JScrollPane(textAreaOne,
57:
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
58:
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
59:
add(new JScrollPane(textAreaTwo,
60:
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
61:
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS));
62:
}
}
Listado 5 JTextAreaDemo.java
La siguiente ventana es desplegada cuando se ejecuta JTextAreaDemo:
En la lnea 52, el mtodo setEditable hace que el rea de texto no sea editable.
VERTICAL_SCROLLBAR_AS_NEEDED
La barra de desplazamiento
vertical debe aparecer slo si
el texto no cabe
verticalmente.
La barra de desplazamiento
horizontal debe aparecer slo
HORIZONTAL_SCROLLBAR_AS_NEEDED
si el texto no cabe
horizontalmente.
VERTICAL_SCROLLBAR_ALWAYS
HORIZONTAL_SCROLLBAR_ALWAYS
VERTICAL_SCROLLBAR_NEVER
HORIZONTAL_SCROLLBAR_NEVER
del texto.
Componente JList
Los componentes de la clase JList permiten al usuario seleccionar uno o ms elementos de
una lista. Un componente JList no debe tener barras de desplazamiento . Si se requieren
barras de desplazamiento, JList es envuelta por JScrollPane, misma que proporciona las
barras de desplazamiento. La clase JListDemo crea una ventana con dos componentes
JList:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
import java.awt.*;
import javax.swing.*;
/**
* Demuestra el componente {@link JList}. Esta clase hereda de
* la clase {@link JPanel}.
*
* @author
* @version 1.0.0
*/
public class JListDemo extends JPanel {
private JList listOne;
private JList listTwo;
private static final String fruitNames[] =
{"Orange", "Pear", "Apple", "Pineapple", "Peach",
"Grapefruit", "Lemon", "Grape"};
/**
* Crea una ventana.
22:
*
23:
* @param args no utilizado.
24:
*/
25:
public static void main(String[] args) {
26:
27:
JFrame frame = new JFrame("JListDemo");
28:
29:
frame.setContentPane(new JListDemo());
30:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
31:
frame.pack();
// Ajusta el tamao de la ventana
32:
frame.setVisible(true);
33:
}
34:
35:
/**
36:
* Crea dos componentes {@link JList}.
37:
*/
38:
public JListDemo() {
39:
40:
setBackground(Color.white);
41:
42:
// Crea los componentes
43:
listOne = new JList(fruitNames);
44:
listTwo = new JList(fruitNames);
45:
46:
// Personaliza las propiedades de la lista
47:
listOne.setVisibleRowCount(5);
48:
listTwo.setVisibleRowCount(5);
49:
listOne.setSelectionMode(
50:
ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
51:
listTwo.setSelectionMode(
52:
ListSelectionModel.SINGLE_SELECTION);
53:
listOne.setFixedCellHeight(15);
54:
listOne.setFixedCellWidth(100);
55:
listTwo.setFixedCellHeight(15);
56:
listTwo.setFixedCellWidth(100);
57:
58:
// Cambia los colores de las listas
59:
listOne.setBackground(new Color(0, 0, 150));
60:
listTwo.setBackground(new Color(0, 150, 0));
61:
listOne.setForeground(Color.white);
62:
listTwo.setForeground(Color.white);
63:
64:
// Aade listas a los contenedores de las barras de
65: desplazamiento
66:
add(new JScrollPane(listOne,
67:
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
68:
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
69:
add(new JScrollPane(listTwo,
70:
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
71:
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS));
72:
}
}
Listado 6 JListDemo.java
La siguiente ventana es desplegada cuando se ejecuta JListDemo:
En las lneas 43 y 44, un constructor JList crea una lista que despliega los
elementos del arreglo especificado. La clase JList tambin proporciona un
constructor de un argumento que toma un arreglo como parmetro de entrada.
SINGLE_SELECTION
SINGLE_INTERVAL_SELECTION
MULTIPLE_INTERVAL_SELECTION
VERTICAL_SCROLLBAR_AS_NEEDED
HORIZONTAL_SCROLLBAR_ALWAYS
VERTICAL_SCROLLBAR_NEVER
HORIZONTAL_SCROLLBAR_NEVER
seleccionado.
arreglo de los elementos
seleccionados.
de los
elementos seleccionados.
Clase ButtonEventsDemo
Clase FruitListDemo
Lecturas:
Requerida:
o Barker, primera edicin, captulo 16 (pginas 52244).
o Barker, segunda edicin, captulo 16 (pginas 735
61).
Secuencia: Lee el libro de texto antes de leer esta pgina.
Esta pgina presenta dos aplicaciones simples que demuestran el manejo de eventos. Estas
aplicaciones tambin muestran cmo deben utilizarse los siguientes componentes:
JLabel
JRadioButton
JTextArea
JList
JButton
Clase ButtonEventsDemo
La clase ButtonEventsDemo contiene tres componentes JRadioButton y un componente
JLabel. Cuando un usuario hace clic en uno de los botones de radio, el texto de la etiqueta
se actualiza. Slo puede seleccionarse un botn de radio a la vez, porque los botones de
radio estn agrupados.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/**
* Demuestra el manejo de eventos para los botones de radio. Esta
clase hereda de
* la clase {@link JPanel}.
*
* @author
* @version 1.0.0
*/
public class ButtonEventsDemo extends JPanel {
private
private
private
private
JRadioButton buttonOne;
JRadioButton buttonTwo;
JRadioButton buttonThree;
JLabel label;
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
/**
* Crea una ventana.
*
* @param args no utilizado.
*/
public static void main(String[] args) {
JFrame frame = new JFrame("ButtonEventsDemo");
frame.setContentPane(new ButtonEventsDemo());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
}
/**
* Crea los componentes.
*/
public ButtonEventsDemo() {
setBackground(Color.white);
// Crea los componentes
buttonOne = new JRadioButton("One", true);
buttonTwo = new JRadioButton("Two");
buttonThree = new JRadioButton("Three");
label = new JLabel(buttonOne.getText());
label.setFont(new Font("Serif", Font.BOLD, 42));
label.setHorizontalAlignment(JLabel.CENTER);
// Agrupa los botones de radio
ButtonGroup group = new ButtonGroup();
group.add(buttonOne);
group.add(buttonTwo);
group.add(buttonThree);
// Cambia los colores de los botones
buttonOne.setBackground(Color.white);
buttonTwo.setBackground(Color.white);
buttonThree.setBackground(Color.white);
// Registra los oyentes (listeners) de los botones de radio.
buttonOne.addActionListener(new ListenerOne());
buttonTwo.addActionListener(new ListenerTwo());
buttonThree.addActionListener(new ListenerThree());
// Agrega botones de radio a un panel
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(3, 1));
panel.add(buttonOne);
panel.add(buttonTwo);
panel.add(buttonThree);
// Crea el diseo
setLayout(new BorderLayout());
add(panel, BorderLayout.WEST);
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100: de
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
add(label, BorderLayout.CENTER);
panel.setBorder(BorderFactory.createEtchedBorder());
label.setBorder(BorderFactory.createLoweredBevelBorder());
}
/**
* Esta clase interna maneja eventos asociados con el botn de
* radio "One".
*/
class ListenerOne implements ActionListener {
/**
* Cambia el texto de la etiqueta.
*
* @param event el objeto del evento.
*/
public void actionPerformed(ActionEvent event) {
label.setText(buttonOne.getText());
}
}
/**
* Esta clase interna maneja los eventos asociados con el botn
* radio "Two".
*/
class ListenerTwo implements ActionListener {
/**
* Cambia el texto de la etiqueta.
*
* @param event el objeto del evento.
*/
public void actionPerformed(ActionEvent event) {
label.setText(buttonTwo.getText());
}
}
/**
* Esta clase interna maneja los eventos del botn de
* radio "Three".
*/
class ListenerThree implements ActionListener {
/**
* Cambia el texto de la etiqueta.
*
* @param event el objeto del evento.
*/
public void actionPerformed(ActionEvent event) {
label.setText(buttonThree.getText());
}
}
Listado 1 ButtonEventsDemo.java
La siguiente ventana es desplegada al ejecutar ButtonEventsDemo:
Clase FruitListDemo
La clase FruitListDemo utiliza tres componentes: un componente JList, uno JTextArea
y uno JButton. El componente JList contiene una lista de frutas y el rea de texto
JTextArea est vaca inicialmente. El usuario puede mover una fruta de la lista al rea de
texto. Cuando el usuario selecciona una fruta, la aplicacin elimina la fruta seleccionada de
la lista y la aade al final del rea de texto. Cuando el usuario hace clic en el botn, la
aplicacin restaura la lista de frutas original y limpia el rea de texto.
1:
2:
3:
4:
import
import
import
import
java.awt.*;
java.awt.event.*;
javax.swing.*;
javax.swing.event.*;
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
import java.util.*;
/**
* Demuestra el manejo de eventos para las listas y botones. Esta
clase
* hereda de la clase {@link JPanel}.
*
* @author
* @version 1.0.0
*/
public class FruitListDemo extends JPanel {
private JList fruitList;
private JButton resetButton;
private JTextArea resultTextArea;
private ArrayList<String> fruitArrayList;
/**
* Crea una ventana.
*
*@param args no utilizado.
*/
public static void main(String[] args) {
JFrame frame = new JFrame("FruitListDemo");
frame.setContentPane(new FruitListDemo());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 290);
frame.setVisible(true);
}
/**
* Crea una Interfaz Grfica del Usuario (GUI).
*/
public FruitListDemo() {
setBackground(Color.white);
setupFruitArrayList();
// Crea los componentes
fruitList = new JList(fruitArrayList.toArray());
resultTextArea = new JTextArea(6, 15);
resetButton = new JButton("Reset Fruit List");
// Personaliza las propiedades del componente
fruitList.setVisibleRowCount(8);
fruitList.setSelectionMode(
ListSelectionModel.SINGLE_SELECTION);
fruitList.setFixedCellHeight(15);
fruitList.setFixedCellWidth(100);
resultTextArea.setEditable(false);
// Registra el oyente (listener) del componente de la lista
62:
fruitList.addListSelectionListener(new FruitListListener());
63:
64:
// Registra el oyente (listener) para el componente de un
65: botn
66:
resetButton.addActionListener(new ResetButtonListener());
67:
68:
// Aade componentes al contenedor
69:
JPanel listPanel = new JPanel();
70:
listPanel.setBackground(Color.white);
71:
listPanel.add(
72:
new JScrollPane(fruitList,
73:
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
74:
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
75:
76:
JPanel textAreaPanel = new JPanel();
77:
textAreaPanel.setBackground(Color.white);
78:
textAreaPanel.add(
79:
new JScrollPane(resultTextArea,
80:
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
81:
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));
82:
83:
setLayout(new BorderLayout());
84:
add(listPanel, BorderLayout.NORTH);
85:
add(resetButton, BorderLayout.CENTER);
86:
add(textAreaPanel, BorderLayout.SOUTH);
87:
}
88:
89:
/*
90:
* Inicializa la coleccin fruitArrayList.
91:
*/
92:
private void setupFruitArrayList() {
93:
94:
fruitArrayList = new ArrayList<String>();
95:
96:
fruitArrayList.add("Orange");
97:
fruitArrayList.add("Pear");
98:
fruitArrayList.add("Apple");
99:
fruitArrayList.add("Pineapple");
100:
fruitArrayList.add("Peach");
101:
fruitArrayList.add("Grapefruit");
102:
fruitArrayList.add("Lemon");
103:
fruitArrayList.add("Grape");
104:
fruitArrayList.add("Banana");
105:
fruitArrayList.add("Tangerine");
106:
}
107:
108:
/**
109:
* Esta clase interna maneja los eventos de la seleccin de la
110: lista.
111:
*/
112:
class FruitListListener implements ListSelectionListener {
113:
114:
/**
115:
* Mueve el elemento seleccionado de la lista al rea de
116: texto.
117:
*
118:
* @param event el objeto del evento.
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
*/
public void valueChanged(ListSelectionEvent event) {
int index = fruitList.getSelectedIndex();
if (! fruitList.getValueIsAdjusting() && index != -1) {
resultTextArea.append(fruitList.getSelectedValue()
+ "\n");
fruitArrayList.remove(index);
fruitList.setListData(fruitArrayList.toArray());
}
}
}
/**
* Esta clase interna maneja los eventos de los botones.
*/
class ResetButtonListener implements ActionListener {
/**
* Restaura la lista a su estado original.
*
* @param event el objeto del evento.
*/
public void actionPerformed(ActionEvent event) {
setupFruitArrayList();
fruitList.setListData(fruitArrayList.toArray());
resultTextArea.setText("");
}
}
}
Listado 2 FruitListDemo.java
La siguiente ventana es desplegada despus que el usuario ha eliminado "Pineapple" (Pia)
y "Grapefruit" (Toronja) de la lista:
En la lnea 47, un constructor JList crea una lista que despliega los elementos de la
coleccin fruitArrayList.
En la lnea 61, el mtodo addListSelectionListener registra el oyente (listener)
de la lista.
En la lnea 64, el mtodo addActionListener registra el oyente (listener) del
botn.
La clase interna FruitListListener, definida en las lneas 109 a 127, maneja los
eventos asociados con la lista:
o En la lnea 118, el mtodo JList.getSelectedIndex obtiene el ndice de la
fruta que ha seleccionado el usuario.
Requerida:
o Barker, primera edicin, captulo 16 (pginas 545
52).
o Barker, segunda edicin, captulo 16 (pginas 761
69).
Secuencia: Lee el libro de texto antes de leer esta pgina.
Esta pgina presenta una aplicacin que utiliza un seleccionador de archivos, un cuadro de
dilogo que permite al usuario examinar el sistema de archivos y seleccionar un archivo (o
directorio) de una lista o introducir el nombre de un archivo (o directorio). El API Swing
provee esta funcionalidad en la clase JFileChooser. El cuadro de dilogo creado por
JFileChooser es modal. Cuando una aplicacin abre un cuadro de dilogo modal, el resto
de la aplicacin deja de responder al usuario, por lo que el usuario est forzado a responder
al cuadro de dilogo. Un JFileChooser puede crear un cuadro de dilogo para abrir un
archivo as como para guardar un archivo: el cuadro de dilogo para abrir un archivo
permite al usuario localizar un archivo, mientras que el cuadro de dilogo para guardar,
permite al usuario especificar el directorio donde ser guardado el archivo y el nombre del
archivo guardado.
import
import
import
import
java.awt.*;
java.awt.event.*;
javax.swing.*;
java.io.*;
/**
* Demuestra la clase {@link JFileChooser}. Esta clase hereda de
* la clase {@link @JPanel}.
*
* @author
* @version 1.0.0
*/
public class TextEditor extends JPanel {
/* Separador de lnea */
private final static String NEW_LINE =
System.getProperty("line.separator");
/* Flujo de error estndar */
private static PrintWriter stdErr =
new PrintWriter(System.err, true);
fileChooser;
/**
* Crea una ventana.
*
* @param args no utilizado.
*/
public static void main(String[] args) {
JFrame frame = new JFrame("TextEditor");
frame.setContentPane(new TextEditor());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400,400);
frame.setVisible(true);
}
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
/**
* Crea una Interfaz Grfica del Usuario.
*/
public TextEditor() {
setBackground(Color.white);
// Crea los componentes
openButton = new JButton("Open");
saveButton = new JButton("Save");
textArea = new TextArea();
fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
// Registra los escuchadores de los botones
openButton.addActionListener(new OpenButtonListener());
saveButton.addActionListener(new SaveButtonListener());
// Agrega componentes al contenedor
setLayout(new BorderLayout());
add(openButton, BorderLayout.NORTH);
add(textArea, BorderLayout.CENTER);
add(saveButton, BorderLayout.SOUTH);
}
/**
* Esta clase interna maneja los clics del botn del botn Open.
*/
class OpenButtonListener implements ActionListener {
/**
* Abre un archivo de texto.
*
* @param event el objeto del evento.
*/
public void actionPerformed(ActionEvent event)
line = input.readLine();
101:
stdErr.println(ioe.toString());
102:
}
103:
}
104:
}
105:
}
106:
107:
/**
108:
* Esta clase intenna maneja los clics del botn para el botn
109: Save.
110:
*/
111:
class SaveButtonListener implements ActionListener {
112:
113:
/**
114:
* Guarda un archivo de texto.
115:
*
116:
* @param event el objeto del evento.
117:
*/
118:
public void actionPerformed(ActionEvent event) {
119:
120:
int result = fileChooser.showSaveDialog(null);
121:
122:
if (result == JFileChooser.APPROVE_OPTION) {
123:
124:
try {
125:
126:
File file = fileChooser.getSelectedFile();
127:
PrintWriter output =
128:
new PrintWriter(new FileWriter(file));
129:
130:
output.print(textArea.getText());
131:
output.close();
132:
} catch (IOException ioe) {
133:
stdErr.println(ioe.toString());
134:
}
135:
}
136:
}
137:
}
}
Listado 1 TextEditor.java
La siguiente figura muestra el seleccionador de archivos para guardar los contenidos del
rea de texto:
o
o
o
En las lneas 125 a 130, la aplicacin crea un PrintWriter y escribe los contenidos
del rea de texto a un archivo con el nombre especificado.
Documentacin de Sun
o Glosario de Trminos Relacionados con Java
o Tutorial de Java
o FAQs. Para encontrar respuestas a las preguntas ms frecuentes.
o Especificacin del Lenguaje Java
Servicios del Desarrollador de Sun. Registrarse para una membresa gratuita.
o Foros de Discusin. Un tablero de noticias interactivo para compartir
conocimiento y preguntas sobre tecnologas de Java y tcnicas de
programacin.
o Sesiones de Chat. Ingenieros de Sun y otras personas con acceso a
informacin del software de Java comparten su conocimiento y perspectivas
sobre los ltimos eventos de la tecnologa de Java en estos chats en lnea.
o Grupos de Usuarios de Java. Un JUG (Java User Group) es un grupo de
personas que comparten un inters comn en la tecnologa de Java y que se
encuentran regularmente para compartir ideas tcnicas e informacin. La
mayora de los JUGs cuentan con listas de correo electrnico donde los
miembros pueden publicar preguntas.
Consejos sobre las Tecnologas Centrales de Java. Un boletn de noticias
mensual que contiene consejos, tcnicos y cdigo ejemplo sobre varios
temas de inters.
Por ltimo, presentamos una lista de algunos libros que podras encontrar interesantes:
Apndice A. Glosario
A
Abstract class (Clase abstracta). Una clase que no puede ser instanciada, slo puede ser
una subclase.
Abstract method (Mtodo abstracto). Un mtodo sin implementacin. El mtodo abstracto
debe ser implementado en una subclase.
Aggregation (Agregacin). Una forma especial de asociacin que indica un relacin "es
parte de".
Accesor method (Mtodo de acceso o accesor). Mtodo para obtener el valor de un
atributo.
Association (Asociacin). Relacin entre dos o ms clases.
C
Class diagram (Diagrama de clase). Representacin grfica que muestra la estructura
esttica del modelo, en particular, la estructura interna de las clases e interfaces y sus
relaciones.
Class method (Mtodo de clase). Mtodo asociado con un nombre de clase.
Class variable (Variable de clase). Variable asociada con un nombre de clase. Todas las
instancias comparten la misma copia de las variables de clase.
Collection (Coleccin). Un objeto que contiene un grupo de objetos, conocido como sus
elementos.
G
Generalization/specialization relationship (Relacin de generalizacin/especializacin).
Representa la relacin es-un. La especializacin/generalizacin entre la clase A y B permite
a una clase A ser definida como especializacin de una clase B ms general.
I
Inheritance (Herencia). Mecanismo que permite extender una clase existente.
Instance method (Mtodo de instancia). Mtodo asociado con un objeto.
Instance variable (Variable de instancia). Variable asociada con un objeto. Cada instancia
mantiene una copia de las variables de instancia de la clase.
Integrated development environment (IDE, Ambiente Integrado de Desarrollo).
Herramientas utilizadas por los desarrolladores de sistemas para asistirlos en las diferentes
fases del desarrollo de un sistema. Normalmente, el IDE incluye un navegador de archivos
M
Multiplicity (Multiplicidad). Multiplicidad indica el nmero de instancias de la clase que
pueden ser asociadas con una nica instancia de otra clase.
Mutator method (Mtodo modificador o mutator). Mtodo para modificar el valor de un
atributo.
O
Object Management Group (OMG o Grupo de Administracin de Objetos). Organizacin
sin fines de lucro que promueve el uso de tecnologa orientada a objetos.
Open source (Cdigo abierto). Software distribuido bajo una licencia que garantiza el
derecho para leer, redistribuir, modificar y utilizar el software libremente.
P
Polymorphism (Polimorfismo). Caracterstica de una referencia que denota instancias de
muchas clases relacionadas por alguna superclase comn. Esta referencia es capaz de
responder a un conjunto de mensaje comn de diferentes maneras.
S
Specialization/generalization relationship (Relacin de especializacin/generalizacin).
Representa la relacin "es un". La especializacin/generalizacin entre la clase A y B
permite a una clase A ser definida como especializacin de una clase B ms general.
Standard error stream object: System.err (Objeto de flujo de error estndar). Un objeto
que permite a un programa pedir informacin y desplegar mensajes de error en pantalla.
Standard input stream object: System.in (Objeto de flujo de entrada estndar). Un
objeto que permite a un programa introducir datos del teclado.
Standard output stream object: System.out (Objeto de flujo de salida estndar). Un
objeto que permite a un programa desplegar una salida regular en pantalla.
U
Unified Modeling Language (UML o Lenguaje Unificado de Modelacin). Un lenguaje
grfico para especificar, visualizar, construir y documentar sistemas de software.
Apndice D. Lecturas
Libro:
Lecturas:
Secciones del Curso
Lecturas
1.1.1 Aplicaciones en
Java
Requerida:
1.1.5 Objetos
Excepcin
Requerida:
1.1.6 Convenciones de
Cdigo
Requerida:
Requerida:
1.1.7 Javadoc
Requerida:
Requerida:
1.2.5 Modelando
Clases
toString
Requerida:
Requerida:
2.1.2 Herencia
Requerida:
2.1.1 Definiendo
Clases
Requerida:
2.1.4 Prueba de
Unidades
Opcional:
Opcional:
2.2.1 Arreglos
Requerida:
2.2.2 ArrayList e
Iteradores
Requerida:
2.3.1 Clases
Abstractas
Requerida:
2.3.2 Polimorfismo
Requerida:
2.3.3 Interfaces
Requerida:
2.3.4 Patrones de
Diseo
7 (pginas 1648).
Barker, segunda edicin,
captulo 7 (pginas 27480).
Opcional:
3.2.1 Componentes y
Contenedores
Swing
Requerida:
3.2.2 Manejo de
Eventos Swing
Requerida:
3.2.3 Clase
16 (pginas 471522).
Barker, segunda edicin,
captulo 16 (pginas 681735).
Requerida:
JFileChooser