Está en la página 1de 14

16 Las Aplicaciones Basadas en Texto

Este capítulo cubre una variedad de temas que ampliarán su conocimiento del Java 2 SDK. Abarca:

 La parametrización del comportamiento de un programa en tiempo de ejecución.


 La lectura y grabación de archivos de texto.
 El manejo de colecciones

16.5 Los Argumentos desde la Línea de Comando

Cuando un programa basado en la tecnología Java se ejecuta desde una ventana de comandos, se
le pueden pasar cero o más argumentos desde la línea de comandos. Ellos son cadenas de
caracteres: una única cadena, como, por ejemplo, arg1, o cadenas de caracteres entre comillas,
como, por ejemplo, "otro argumento".

La secuencia de argumentos se escribe a continuación del nombre de la clase del programa y se


almacena en un arreglo de objetos String pasados al método estático main. (ver Figura )

Este programa despliega cada argumento pasado al programa TestArgs desde la línea de
comandos. Por ejemplo, la ejecución del programa anterior con los siguientes argumentos produce
la salida que se detalla:

java TestArgs arg1 arg2 "another arg"


args[0] is 'arg1'
args[1] is 'arg2'
args[2] is 'another arg'

1. public class TestArgs {


2. public static void main(String[] args) {
3. for ( int i = 0; i < args.length; i++ ) {
4. System.out.println("args[" + i + "] is '"
+ args[i] + ";
5. }
6. }
7. }

16.6 Las Propiedades del Sistema

Las propiedades del sistema son otro mecanismo para indicar parámetros en un programa en
tiempo de ejecución. Una propiedad es una correspondencia entre un nombre de propiedad y un
valor. Ambos elementos son cadenas de caracteres. La clase Properties representa esta clase de
correspondencias. El método System.getProperties devuelve el objeto de las propiedades del
sistema. El método System.getProperty(String) devuelve el valor, como cadena de caracteres,
de la propiedad cuyo nombre es el explicitado en el parámetro String. El método
System.getProperty(String, String) ofrece un valor por defecto (el segundo parámetro), el cual
es devuelto en caso de que el nombre de la propiedad pasada como primer argumento no exista en
el sistema.
Hay también miembros estáticos en las clases de envoltura que realizan conversiones de los valores
de las propiedades: Boolean.getBoolean(String), Integer.getInteger(String) y
Long.getLong(String). El argumento de tipo String es el nombre de la propiedad. Si la propiedad
no existe, entonces devolverá false o null (respectivamente).

16.7 La Clase Properties

Un objeto de la clase Properties contiene una correspondencia entre los nombres de la propiedad
(String) y sus valores (String). Tiene dos métodos principales para devolver la propiedad de un
valor: getProperty(String) y getProperty(String, String). Este último ofrece la posibilidad de
especificar un valor por defecto, el cual será devuelto si el nombre de la propiedad pasado como
parámetro no existe.

Puede iterar a través de un conjunto completo de nombres de propiedades usando el método


propertyNames y, llamando a getProperty en cada nombre, puede devolver todos los valores.

Finalmente, el conjunto de propiedades puede ser almacenado y recuperado de cualquier flujo de


entrada/salida usando los métodos load y store. El programa en la Figura lista el conjunto
completo de propiedades que existe en el momento en que se ejecuta el programa

La Línea 6 obtiene el conjunto de propiedades del sistema y la Línea 7 recupera una enumeración
de todos los nombres de las propiedades en el conjunto de propiedades.

Se utiliza un objeto Enumeration para iterar sobre los elementos en una colección. Este es muy
similar a un Iterator, el cual se describe en "Iteradores", apartado 9.10

El método hasMoreElements devuelve el valor true si hay más elementos sobre los cuales iterar y
el método nextElement devuelve el siguiente elemento en la enumeración.

La Línea 11 devuelve el valor de la propiedad y las líneas 12-13 despliegan el nombre y el valor de
la propiedad.

java -DmyProp=theValue TestProperties

La Figura es un extracto de la salida.

Fig 1

1 import java.util.Properties;
2 import java.util.Enumeration;
3
4 public class TestProperties {
5 public static void main(String[] args) {
6 Properties props = System.getProperties();
7 Enumeration propNames = props.propertyNames();
8
9 while ( propNames.hasMoreElements() ) {
10 String propName = (String)
propNames.nextElement();
11 String property = props.getProperty(propName);
12 System.out.println("property '" + propName
13 + "' is '" + property + "'");
14 }
15 }
Fig 2

property 'java.vm.version' is '1.4.0'


property 'java.compiler' is 'NONE'
property 'path.separator' is ':'
property 'file.separator' is '/'
property 'user.home' is '/home/basham'
property 'java.specification.vendor' is 'Sun Microsystems Inc.'
property 'user.language' is 'en'
property 'user.name' is 'basham'
property 'myProp' is 'theValue'

16.8 La Consola de EntradaSalida

La mayoría de las aplicaciones deben interaccionar con el usuario. Algunas veces, esta interacción
se lleva a cabo a través de la entrada de un texto y de la salida en la consola (usando el teclado
como entrada estándar y la ventana de comandos como la salida estándar).

Java 2 SDK soporta una consola de Entrada/Salida (E/S) con tres variables públicas, en la clase
java.lang.System:

 La variable System.out es un objeto PrintStream que referencia (inicialmente) a la


ventana de comandos que lanza la aplicación de tecnología Java.
 La variable System.in es un objeto InputStream que referencia (inicialmente) al teclado
del usuario.
 La variable System.err es un objeto PrintStream que referencia (inicialmente) a la
ventana de comandos que lanzó la aplicación de tecnología Java.

Es posible cambiar esta asignación de flujos usando los métodos static:

System.setOut, System.setIn y System.setErr.

Por ejemplo, se puede cambiar el flujo de error estándar a un flujo de archivo.

16.8.1 La Escritura a la Salida Estándar

Se puede escribir a la salida estándar a través del método System.out.println(String). Este


método de la clase PrintStream despliega el argumento String a la consola y agrega un carácter
de nueva línea al final. Los siguientes métodos son también soportados para desplegar otros tipos:
primitivos, un buffer de caracteres y un objeto arbitrario. Todos agregan un carácter de nueva línea
al final de la salida.

void println(boolean)
void println(char)
void println(double)
void println(float)
void println(int)
void println(long)
void println(char[])
void println(Object)
Existe un conjunto de métodos sobrecargados, denominados print, que no agregan el
carácter de nueva línea

16.8.2 La Lectura de la Entrada Estándar

El ejemplo en la Figura muestra una técnica que se debería usar para leer información en un
objeto String desde la consola de entrada estándar

La Línea 5 declara una variable String de nombre s, que el programa usa para mantener cada línea
leída de la entrada estándar. La Líneas 8-10 asocian el System.in con dos objetos de soporte que
manejan el flujo de bytes provenientes de la entrada estándar. El objeto ir de la calse
InputStreamReader lee caracteres y los convierte en bytes en
caracteres Unicode. El objeto in asociado a la clase BufferedReader provee el método readLine, el
cual permite al programa leer desde la entrada estándar de una línea a la vez.

El código para KeyboardInput continúa en la Figura

La Línea 15 lee la primera línea del texto desde la entrada estándar. La iteración while (Líneas 16-
19) despliega en forma iterativa la línea actual y lee la línea siguiente. Este código puede ser
reescrito de forma más concisa (pero más críptica) como (ver Figura )

Dado que el método readLine puede lanzar una excepción de E/S, se debe incluir todo el código en
un bloque try-catch. (ver Figura )

La Línea 23 cierra el flujo de entrada más lejano para liberar cualquier recurso del sistema
relacionado con crear ese flujo de objetos. (ver Figura )

Finalmente, el programa maneja cualquier excepción de I/O que pueda ocurrir.

Fig 1

1 import java.io.*;
2
3 public class KeyboardInput {
4 public static void main (String[] args) {
5 String s;
6 // Create a buffered reader to read
7 // each line from the keyboard.
8 InputStreamReader ir
9 = new InputStreamReader(System.in);
10 BufferedReader in = new BufferedReader(ir);
11
12 System.out.println("Unix: Type ctrl-d to exit." +
13 "\nWindows: Type ctrl-z to exit");

Fig 2

14 try {
15 // Read each input line and echo it
16 s = in.readLine();
17 while ( s != null ) {
18 System.out.println("Read: " + s);
19 s = in.readLine();
20 }

while ( (s = in.readLine()) != null ) {


System.out.println("Read: " + s);
}

Fig 4

21
22 // Close the buffered reader.
23 in.close();

Fig 5

24 }catch (IOException e) { // Catch any exceptions.


25 e.printStackTrace();
26 }
27 }
28 }

16.8.3 La Salida con Formato Simple

El lenguaje de programación Java versión 1.5 provee la funcionalidad de printf, al estilo del
lenguaje C. Este ofrece salida formateada estándar desde el programa, la que permite a los
programadores migrar código heredado. Se puede usar el método printf siguiendo la sintaxis normal
de C y C++. Esta funcionalidad de formateo está también disponible en la
clase String en el método format. Se puede usar el método printf como sigue:

System.out.printf("name count\n");
String s = String.format("%s %5d%n", user, total);

La Tabla en la Figura muestra algunos códigos de formato comunes.

Se puede usar %n para los caracteres de nueva línea, en lugar del \n, para la
independencia de plataforma.

16.8.4 La Entrada con Formato Simple

La clase Scanner ofrece la funcionalidad de entrada formateada, que es parte del paquete
java.util. Dicho paquete ofrece métodos para obtener valores primitivos y para realizar bloqueos
mientras espera por una entrada desde el usuario. Un ejemplo se muestra en el Código de la Figura
.

En el Código dela Figura , la Línea 5 crea una referencia a Scanner pasándole directamente la
entrada de la consola. La línea 6 recupera el valor de la cadena de caracteres desde la entrada
dada usando el método next de Scanner. La línea 8 obtiene el valor entero de la entrada dada
usando el método nextInt. La línea 10 cierra la entrada para el usuario.

1 import java.io.*;
2 import java.util.Scanner;
3 public class ScanTest {
4 public static void main(String [] args) {
5 Scanner s = new Scanner(System.in);
6 String param = s.next();
7 System.out.println("the param 1" + param);
8 int value = s.nextInt();
9 System.out.println("second param" + value);
10 s.close();
11 }
12 }

16.9 Los Archivos de EntradaSalida (ES)

La E/S es uno de los más importantes elementos de programación. La tecnología Java incluye un
rico conjunto de flujos de E/S. En la sección previa se mostró cómo usar los flujos para comunicarse
con el usuario a través de la salida estándar (usualmente una ventana de comandos) y la entrada
estándar (usualmente el teclado). Esta sección examina varias
técnicas simples para leer y escribir archivos con foco en los datos de los caracteres, incluyendo:

 Creación de objetos File.


 Manipulación de objetos File.
 Lectura y escritura al flujo de archivo.

16.9.1 La Creación de un Nuevo Objeto File

La clase File provee varias utilidades para manejar archivos y obtener información de ellos. En la
tecnología Java, un directorio es otro archivo. Puede crear un objeto File que representa un
directorio y luego usarlo para identificar otros archivos, como se muestra en la tercera viñeta.

 File myFile;
myFile = new File("myfile.txt");
 myFile = new File("MyDocs", "myfile.txt");
 File myDir = new File("MyDocs");
myFile = new File(myDir, "myfile.txt");

El constructor que se usa, frecuentemente depende del objeto archivo al que se quiera acceder.

Por ejemplo, si se usa sólo un archivo en la aplicación, se utiliza el primer constructor. Sin embargo,
si se utilizan varios archivos de un directorio común, se sugiere usar el segundo o el tercer
constructor, ya que debería ser más fácil.

define métodos independientes de la plataforma para manipular un archivo


La clase File
mantenido por un sistema de archivos nativos. Sin embargo, no se le permite acceder al
contenido del archivo.

16.9.2 Las Utilidades y Pruebas de File

Después de haber creado un objeto File, se puede usar cualquier método en la siguiente sección
para recoger información acerca del archivo.

El Nombre de Archivo
Los siguientes métodos retornan nombres de archivos:

 String getName()
 String getPath()
 String getAbsolutePath()
 String getParent()
 boolean renameTo(File newName)

Las Utilidades de Directorio

Los siguientes métodos proveen utilidades de directorio:

 boolean mkdir()
 String[] list()

La Información General de Archivo y Utilidades

Los siguientes métodos retornan información general de archivos:

 long lastModified()
 long length()
 boolean delete()

La Verificación de Archivos

Los siguientes métodos devuelven información acerca de los atributos del archivo:

 boolean exists()
 boolean canWrite()
 boolean canRead()
 boolean isFile()
 boolean isDirectory()
 boolean isAbsolute()

16.9.3 El Flujo de ES de Archivos

La plataforma J2SE soporta entrada de archivos de dos formas:

 Usando la clase FileReader para leer caracteres.


 Usando la clase BufferedReader para usar el método readLine.

La plataforma J2SE soporta la salida de archivos de dos formas:

 Usando la clase FileWriter para escribir caracteres.


 Usando la clase PrintWriter para usar los métodos print y println.

Ejemplo de la Entrada desde un Archivo

El código en la Figura lee un archivo de texto y reproduce cada línea a la salida estándar, la cual
despliega el archivo.

La Línea 5 crea un nuevo objeto File basado en el primer argumento pasado desde la línea de
comando. Las Líneas 10 y 11 crean un buffered reader que contiene un lector de
archivos. Este código lanza una FileNotFoundException, si el archivo no existe.
El Código de la Figura lee un archivo de texto y reproduce cada línea a la salida estándar. De
esta manera, se despliega el archivo. En éste Código, la iteración while en las Líneas 15-19 realiza
exactamente lo mismo que el programa KeyboardInput. Este lee cada línea de texto en el
buffered reader y lo reproduce en la salida estándar.La Línea 21 cierra el buffered reader, que, a
su vez, cierra el lector de archivo asociado al buffer del archivo.El código de manejo de excepción
entre las Líneas 23-25 atrapa la excepción FileNotFoundException que puede ser lanzada por el
constructor FileReader. Las Líneas 27-30 manejan cualquier otra excepción basada en I/O que
pueda ser lanzada (por los métodos readLine y close).

Ejemplo de Salida a Archivo

El Código de la Figura lee líneas de la entrada desde el teclado y envía cada una de ellas a un
archivo.

Al igual que el Código de la Figura , la Línea 6 del Código de la Figura crea un objeto File,
basado en el primer argumento de la línea de comandos. Las Líneas 10-11 crean un flujo de lectura
de caracteres desde el flujo binario (System.in). Las Líneas 12-13 crean un buffered reader para la
entrada estándar. Las Líneas 15-16 crean un print writer asociado a un file writer para el archivo
creado en la Línea 6.

Las Líneas 19-20 (ver Figura ) indican al usuario que debe ingresar las líneas de texto que serán
grabadas en el archivo y que presione Control-d para finalizar dicho ingreso. Las Líneas 23-25 leen
del flujo de entrada y graban en el archivo, de una línea por vez.

Las Líneas 28 y 29 cierran los flujos de entrada y salida. Las Líneas 31-33 manejan las excepciones
de I/O que deben ser lanzadas. (ver Figura )

Fig 1

1 import java.io.*;
2 public class ReadFile {
3 public static void main (String [] args) {
4 // Crea el archivo
5 File file = new File(args[0]);
6
7 try {
8 // Crea un buffered reader
9 // para leer cada línea del archivo.
10 BufferedReader in
11 = new BufferedReader(new FileReader(file));
12 String s;
13

Fig 2

14 // Lee cada linea del archivo


15 s = in.readLine();
16 while (s != null) {
17 System.out.println("Read: " + s);
18 s = in.readLine();
19 }
20 // Cierra el buffered reader
21 in.close();
22
23 } catch (FileNotFoundException e1) {
24 // Si este archivo no existe
25 System.err.println("File not found: " + file);
26
27 } catch (IOException e2) {
28 // Atrapa cualquier otra excepcion IO.
29 e2.printStackTrace();
30 }
31 }
32 }

Fig 3

1 import java.io.*;
2
3 public class WriteFile {
4 public static void main (String[] args) {
5 // Crear Archivo
6 File file = new File(args[0]);
7
8 try {
9 // Crea un buffered reader
10 InputStreamReader isr
11 = new InputStreamReader(System.in);
12 BufferedReader in
13 = new BufferedReader(isr);
14 // Crea un escritor de la impresora en este archivo.
15 PrintWriter out
16 = new PrintWriter(new FileWriter(file));
17 String s;

Fig 4

18
19 System.out.print("Enter file text. ");
20 System.out.println("[Type ctrl-d to stop.]");
21
22 // Lee cada línea de ingreso
23 while ((s = in.readLine()) != null) {
24 out.println(s);
25 }
26

Fig 5

27 // Cierra el buffer de escritura


28 in.close();
29 out.close();
30
31 } catch (IOException e) {
32 // Atrapa cualquier excepci¨®n de IO.
33 e.printStackTrace();
34 }
35 }
36 }
16.10 La API de Colecciones

Una colección es un objeto simple que representa un grupo de objetos, llamados elementos.
Típicamente, las colecciones tratan con muchos objetos, todos de un tipo en particular (esto es,
todos descienden del mismo tipo padre)

 Collection - Un grupo de objetos, conocidos como elementos. La implementación


determina si hay un orden específico y si se permiten elementos duplicados.
 Set - Una colección desordenada en la que no se admiten elementos duplicados.
 List - Una colección ordenada en la que se admiten elementos duplicados.

Las colecciones mantienen referencias a objetos del tipo Object. Esto permite que cualquier objeto
pueda guardarse en una colección. También necesita el uso de una correcta conversión de tipos
antes de usar el objeto y luego de recuperarlo de la colección.

La Figura muestra un diagrama UML primario con las interfaces yl las clases de implementación
de la API de colecciones.La clase HashSet da una implementación de la interfaz Set. Las clases
ArrayList y LinkedList suministran una implementación de la interfaz List .

16.10.1 Un Ejemplo Set

En el ejemplo de la Figura , el programa declara una variable (set) del tipo Set y la inicializa con
un nuevo objeto HashSet. Luego, le agrega algunos elementos y envía el conjunto a la salida
estándar. El intento de agregar los ítems duplicados en las líneas 11 y 12 falla; de esa manera, el
método add devuelve el valor false.

La salida generada del programa debe ser:

[one, second, 5.0, 3rd, 4]

1. import java.util.*;
2.
3. public class SetExample {
4. public static void main(String[] args) {
5. Set set = new HashSet();
6. set.add("one");
7. set.add("second");
8. set.add("3rd");
9. set.add(new Integer(4));
10. set.add(new Float(5.0F));
11. set.add("second"); // duplicado, no se agrega
12. set.add(new Integer(4)); // duplicado, no se agrega
13. System.out.println(set);
14. }
15. }
16.10.2 Un Ejemplo de List

En el siguiente ejemplo, el programa declara una variable (list) del tipo List y es inicializada a un
nuevo objeto ArrayList. Este, luego agrega unos pocos elementos y despliega la lista en la salida
estándar. Dado que las listas le permiten duplicados, las Líneas 11 y 12 son exitosas.

La salida generada desde el programa es:

[one, second, 3rd, 4, 5.0, second, 4]

1 import java.util.*;
2
3 public class ListExample {
4 public static void main(String[] args) {
5 List list = new ArrayList();
6 list.add("one");
7 list.add("second");
8 list.add("3rd");
9 list.add(new Integer(4));
10 list.add(new Float(5.0F));
11 list.add("second"); // // duplicado, se agrega
12 list.add(new Integer(4)); // // duplicado, se
agrega
13 System.out.println(list);
14 }
15 }

16.10.3 Las Colecciones en la JDK Versión 1.1

La API de Colecciones es una característica mejorada de la Java 2 SDK, aunque existían unas
pocas clases de colecciones en la JDK versión 1.0 y JDK versión 1.1. Estas clases todavía existen
en el SDK con la misma interfaz, pero han sido actualizadas para interaccionar con la nueva API de
colecciones.

La clase Vector implementa la interfaz List. La clase Stack es una extensión de Vector que agrega
las típicas operaciones de stack: push, pop y peek. HashTable es una implementación de Map. La
clase Properties (vista en "Propiedades del Sistema" en el apartado 9.4) es una extensión de
HashTable que sólo usa String para las claves y los valores.

Cada una de estas colecciones tiene un método elements que devuelve un objeto Enumeration. La
interfaz Enumeration es una interfaz similar a la interfaz Iterator, pero incompatible con ella. Por
ejemplo, hasNext es reemplazado por hasMoreElements en la interfaz Enumeration .

16.11 Los Genéricos

Las clases de Collection usan el tipo Object para permitir diferentes entradas y tipos de retorno.
Usted necesita convertirlos explícitamente para obtener el objeto que necesita. Esto no es seguro.
La solución para este problema es hacer uso de la funcionalidad genérica. Esta provee información
para el compilador acerca del tipo de colección usada. Por lo tanto, la verificación de tipos está
resuelta automáticamente en tiempo de ejecución. Esto elimina la conversión explícita de los tipos
de datos a ser usados en la colección. Con la adición del autoboxing a los tipos primitivos, se
pueden usar genéricos y escribir un código más simple y comprensible.

Antes de usar genéricos, el código podría aparecer como:

ArrayList list = new ArrayList();


list.add(0, new Integer(42));
int total = ((Integer)list.get(0)).intValue();

En el segmento de código previo se necesita una clase de envoltura Integer para convertir los tipos
(typecasting) mientras traen el valor entero de la lista. En tiempo de ejecución, el programa
necesita verificar el tipo para la lista. El ArrayList debería haberse declarado como
ArrayList<Integer>, de manera que el compilador esté informado sobre el tipo de la colección a
ser usada. Mientras que, al recuperar el valor, no hay necesidad de una clase de envoltura Integer.

El uso de genéricos para este mismo código se describe aquí:

ArrayList<Integer> list = new ArrayList<Integer>();


list.add(0, new Integer(42));
int total = list.get(0).intValue();

La facilidad de autoboxing y la mejora para la iteración se adecuan perfectamente a la API Generic.


Usando autoboxing este ejemplo de código podría ser escrito como:

ArrayList<Integer> list = new ArrayList<Integer>();


list.add(0, 42);
int total = list.get(0);

La Figura muestra un diagrama UML de las interfaces primarias y la implementación


de las clases para la API de Colecciones.

16.11.1 Las Advertencias del Compilador

Cuando usa el nuevo compilador de J2SE versión 5 con código que ya tenía escrito o no genérico,
usted debe ver una advertencia (warning) especial. Una clase de ejemplo que envía esta
advertencia es la ilustrada en el Código de la Figura

Si usted solamente compila esta clase usando el siguiente comando:

javac GenericsWarning.java

verá la siguiente advertencia:

Note: GenericsWarning.java uses unchecked or unsafe operations.


Note: Recompile with -Xlint:unchecked for details.

Si compila esta clase usando el siguiente comando:

javac -Xlint:unchecked GenericsWarning.java

verá la siguiente advertencia:

GenericsWarning.java:5: warning: [unchecked] unchecked call


to add(int,E) as a member of the raw type java.util.List
list.add(0, new Integer(42));
^
1 warning

Estas son solo advertencias. La clase compila bien y esas advertencias pueden ser ignoradas. Sin
embargo, puede usarlas para recordarle de modificar su código para que este sea un código
generic-friendly. Para resolver esta advertencia, necesitará cambiar la Línea 4:List<Integer>
list = new ArrayList<Integer>();

1 import java.util.*;
2 public class GenericsWarning {
3 public static void main(String[] args) {
4 List list = new ArrayList();
5 list.add(0, new Integer(42));
6 int total = ((Integer)list.get(0)).intValue();
7 }
8 }

16.12 Los Iteradores

Usted puede explorar una colección usando un iterador. La interfaz básica Iterator le permite
explorar hacia adelante una colección. En el caso de una iteración sobre un conjunto, el orden no es
determinante.. El orden de una iteración sobre una lista que se mueve hacia adelante a través de los
elementos. Un objeto List también soporta un ListIterator, el cual permite recorrer la lista hacia
atrás.

El siguiente fragmento de código demuestra el uso de un iterador.

List list = new ArrayList();


// agrega algunos elementos
Iterator elements = list.iterator();
while ( elements.hasNext() ) {
System.out.println (elements. next());
}

La Figura muestra un diagrama UML de la interfaz genérica Iterator para la API de Colecciones.

El método remove permite al código borrar el ítem actual en la iteración (el ítem devuelto por el
método next o previous más reciente). Si el método remove no es soportado por la colección
subyacente, entonces se produce una excepción de tipo Unsupported OperationException.

Mientras se usa una ListIterator, es común moverse a través de la lista sólo en una dirección: o
hacia delante usando next o hacia atrás usando previous. Si usa el previous inmediatamente
después del next, entonces recibirá el mismo elemento; así como si se llama a next después de
previous.

El método set cambia el elemento de la colección que está siendo referenciado por el cursor del
iterador. El método add inserta el nuevo elemento dentro de la colección inmediatamente antes del
cursor del iterador. Por lo tanto, si llama a previous después de add, entonces devolverá el elemento
recién agregado. Sin embargo, una llamada a next no se verá afectada. Si la colección subyacente
no soporta el método set o el método add, entonces lanzará una excepción del tipo Unsupported
OperationException.

16.12.1 La Iteración for Mejorada


Se puede iterar a través de una colección en una forma mucho más simple con el uso de las
iteraciones for mejoradas. Las iteraciones for mejoradas hacen el recorrido a través de una
colección de manera simple, clara y segura. Los iteradores son propensos a errores por las
siguientes razones:

 Las variables de los iteradores ocurren tres veces por iteración.


 Esto crea la oportunidad al código de volverse erróneo.

Una iteración for mejorada supera estas fallas asignando directamente el objeto Collection a la
variable iterator en la iteración for. Se puede usar al recorrer los elementos de un arreglo además
de eliminar la necesidad del elemento índice mientras recorre los elementos de un arreglo. El uso de
las iteraciones for mejoradas comparada con los iteradores se ilustra a continuación:

public void deleteAll(Collection<NameList> c) {


for ( Iterator<NameList> i=c.iterator(); i.hasNext(); ) {
NameList nl = i.next();
nl.deleteItem();
}
}

En el segmento de código previo, el método deleteAll usa la variable i tres veces en el bucle for y
produce la opción de error cuando se usa la variable por segunda vez. También, la iteración for usa
el método hasNext de Iterator para obtener el próximo elemento a ser procesado. Será difícil para
usted recordar todos estos métodos. La iteración for mejorada elimina el uso de métodos de
iteración separados y minimiza el número de ocurrencias de la variable de iteración. El método
deleteAll con la iteración for mejorada se ilustra a continuación:

public void deleteAll(Collection<NameList> c) {


for ( NameList nl : c ) {
nl.deleteItem();
}

La iteración for mejorada en arreglos le permite recorrer a través de los elementos del arreglo sin
usar una variable índice para él. Esto se ilustra en el siguiente segmento de código.

public int sum(int[] array) {


int result = 0;
for ( int element : array ) {
result += element;
}
return result;
}

Con la funcionalidad de la iteración for mejorada, el recorrido de los for anidados se hace simple y
fácil de comprender reduciendo la ambigüedad de las variables que están siendo usadas en las
iteraciones for anidadas.

List<Subject> subjects=...;
List<Teacher> teachers=...;
List<Course> courseList = ArrayList<Course)();
for ( Subject subj : subjects ) {
for ( Teacher tchr : teachers ) {
courseList.add(new Course(subj, tchr));
}
}

También podría gustarte