Observe el uso de un ArrayList -- parte del "Collections Framework" -- sin utilizar clases genéricas :
import java.util.*; public class Idiomas { public static void main(String args[]) { // Definir un ArrayList List lenguajes = new ArrayList(); lenguajes.add("ingles"); lenguajes.add("castellano"); lenguajes.add("aleman"); lenguajes.add(new StringBuffer("Error solo hasta ejecutarse programa!")); // Definir Iterator para extraer/imprimir valores for( Iterator it = lenguajes.iterator(); it.hasNext(); ) { String x = (String)it.next(); System.out.println(x); } } } |
Primeramente observe que en el ArrayList
son insertados una serie de String's
y al final es colocado un StringBuffer
, esto tipo de error no es detectado por el compilador, inclusive la única manera en que es detectada esta falla es hasta que se intentan accesar los valores del mismo ArrayList
, una detección simple en esta clase sencilla, pero un proceso que se puede tornar complicado si los valores son accesados en diversas librerías. Además, note que al momento de iterar sobre la colección de objetos también es necesario hacer un "cast" explicito hacia String
sobre todo valor.
Ahora intente compilar esta misma clase utilizando la versión JDK 5, y observará un mensaje como el siguiente :
Note: Idiomas.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. |
El compilador del JDK 5 detecta que la clase contiene operaciones inseguras, en este caso, no definir el tipo de objetos esperados en la clase del "Collections Framework". Si recompila la clase con la opción -Xlint
, observará una lista detallada de las operaciones consideradas inseguras por Java 5.
Ahora observemos la misma clase modificada para utilizar clases genericas :
import java.util.*; public class Idiomas { public static void main(String args[]) { // Definir un ArrayList List<String> lenguajes = new ArrayList<String>(); lenguajes.add("ingles"); lenguajes.add("castellano"); lenguajes.add("aleman"); //lenguajes.add(new StringBuffer("Error detectado al compilar")); // Definir Iterator para extraer/imprimir valores for( Iterator<String> it = lenguajes.iterator(); it.hasNext(); ) { String x = it.next(); // No existe "cast" explicito System.out.println(x); } } } |
La nomenclatura utilizada por clases genéricas es <Tipo de Clase>
, misma que debe ser utilizada en la referencia de la colección, al inicializar la clase y al momento de extraerla en el iterador. Al emplear este mecanismo, cualquier intento de colocar un tipo de objeto distinto aquel definido en la clase genérica, resulta en un error al momento de compilar.
El proceso para utilizar clases genéricas en listas de valores (key-value lists) -- interfase Map
-- es muy similar al de listas, observemos el siguiente ejemplo:
import java.util.*; public class Agenda { public static void main(String args[]) { // Definir un HashMap Map<String, Object> global = new HashMap<String, Object>(); // Insertar valores "key"-"value" al HashMap global.put("Doctor", "(+52)-4000-5000"); global.put("Casa", "(888)-4500-3400"); global.put("Hermano", "(575)-2042-3233"); // Definir Iterator para extraer/imprimir valores for( Iterator<String> it = global.keySet().iterator(); it.hasNext();) { String s = it.next(); Object s1 = global.get(s); System.out.println(s + " : " + s1); } } } |
La nomenclatura de < >
permanece idéntica, sin embargo, debido a que se trata de listas de valores, es agregado primeramente el tipo de clase para el identificador ("key") y posteriormente el tipo de clase para el valor. Nótese también que como parámetro de clase genérica es utilizado la clase universal Object
, esto es un indicador de la flexibilidad con que pueden ser empleadas clases genéricas en un diseño, pudiendo ser cualquier tipo de clase para restringir el tipo de objetos colocados en una colección.
NOTA: Tome en cuenta que al utilizar la clase Object
como clase genérica estaría perdiendo todas las salvaguardas ofrecidas por esta funcionalidad, lo anterior se debe a que todo objeto es derivado directamente de esta clase universal. Al definir una colección con clase genérica Object
no recibiría ningún tipo de error ya que todo objeto proviene de la jerarquía de herencias en Object
.