Bienvenidos sean a este post, hoy hablaremos sobre los genericos los cuales permiten a los programadores especificar con una simple declaracion un grupo de metodos relacionados o con una simple declaracion de la clase, tambien nos da la posibilidad de poder capturar los tipos invalidos en el momento de compilacion.
Usando el concepto genérico de Java, podríamos escribir un método genérico para clasificar un array de objetos, luego invocar el método genérico con arrays de enteros, arrays dobles, arrays de cadenas, etc., para ordenar los elementos del array.
Hablemos primero sobre los metodos genericos, un metodo generico es uno capaz de poder ser declarado y luego puede ser llamado con diferentes tipos de argumentos, basado en los tipos de argumentos pasado al metodo generico y el compilador manejara cada llamado a los metodos apropiadamente y por ultimo veamos algunas reglas para definir un metodo generico:
- Todos los metodos genericos tienen una definicion de tipo de parametro delimitado por los signos de mayor y menor (< >) que precede al tipo de valor que retorna el metodo
- Cada definicion de tipo de parametro contiene uno o mas tipos de parametros separados por una coma, el tipo de parametro (tambien conocido como tipo de variable) es un identificador que especifica un tipo de nombre generico
- Estos parametros pueden ser usados para declarar que tipo devuelve y actua como contenedores para los tipos de argumentos informados en el metodo generico, las cuales son conocidas como argumentos de tipo actual
- El cuerpo de un metodo generico se declara como cualquier otro metodo
Para entender un poco mejor el concepto veamos el siguiente ejemplo:
DemoMetodoGenerico.java:
public class DemoMetodoGenerico
{
public static < E > void printArray( E[] inputArray )
{
for(E elemento : inputArray)
{
System.out.printf("%s ", elemento);
}
System.out.println();
}
public static void main(String[] args)
{
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] dblArray = { 1.1, 2.2, 3.3, 4.4, 5.5 };
Character[] chrArray = { 'H', 'O', 'L', 'A', '!' };
System.out.println("intArray contiene: ");
printArray(intArray);
System.out.println("\ndblArray contiene: ");
printArray(dblArray);
System.out.println("\nchrArray contiene: ");
printArray(chrArray);
}
}
En este ejemplo tendremos un metodo generico llamado printArray el cual es este bloque:
public static < E > void printArray( E[] inputArray )
{
for(E elemento : inputArray)
{
System.out.printf("%s ", elemento);
}
System.out.println();
}
En las clases genericas crearemos el tipo de parametro, en este caso es E y esta encerrado entre los signos de mayor y menor (< >), en este bloque usamos E pero puede ser cualquier letra no esta relacionado a ninguna asociacion, despues tenemos el nombre del metodo, printArray, y en los atributos observen como usamos el generico (E) le decimos que va a ser tipo array y por ultimo le asignamos un identificador, despues tendremos un for mejorado para obtener cada uno de los elementos informados a inputArray y utilizara el parametro E para iniciar a elemento, en el bucle mostraremos cada uno de los elementos del array, si se preguntan el %s es para informarle al printf que debe mostrarlo en formato String, con esto acabaria nuestro metodo generico, nuestro siguiente paso sera el programa en si, para ello crearemos tres arrays: uno de tipo entero (Integer), otro de tipo doble (Double) y finalmente uno de tipo caracteres (Character) pueden ver que no utilizamos los tipos primitivos (int, char, double) porque este tipo de metodos no los puede trabajar y solo puede trabajar con los tipos de referencia, en ellos almacenamos la informacion y despues enviaremos a cada uno de ellos a nuestro metodo generico para procesarlo y mostrarlo, compilemos, ejecutemos y veamos su salida:
tinchicus@dbn001vrt:~/programacion/java/codigo$ java DemoMetodoGenerico
intArray contiene:
1 2 3 4 5
dblArray contiene:
1.1 2.2 3.3 4.4 5.5
chrArray contiene:
H O L A !
tinchicus@dbn001vrt:~/programacion/java/codigo$
Observen como con un solo metodo pudimos procesar tres tipos distintos de datos, en lugar de tener un metodo para cada uno de ellos, esto es gracias al tipo de parametro que asignamos el cual permite al metodo adaptarse al tipo que debe manipular pero en algunas ocasiones necesitaremos restringir algunos tipos que sera permitidos como tipo de parametro, esto se llama Tipo de Parametro limitado, un ejemplo puede ser un metodo que opera numeros solo acepte instancias o subclases solamente de numeros, para declarar este tipo de limites primero declararemos el tipo de parametro seguido de la palabra extends y por ultimo su limite superior, veamos el siguiente ejemplo:
ValorMaximo.java:
public class ValorMaximo
{
public static <T extends Comparable<T>> T maximum(T x, T y, T z)
{
T max = x;
if (y.compareTo(max)>0)
max = y;
if (z.compareTo(max)>0)
max = z;
return max;
}
public static void main(String[] args)
{
System.out.printf("Maximo de %d, %d, %d es %d\n\n",
3, 4, 5, maximum( 3, 4, 5));
System.out.printf("Maximo de %.1f, %.1f, %.1f es %.1f\n\n",
6.6, 7.7, 8.8, maximum( 6.6, 7.7, 8.8));
System.out.printf("Maximo de %s, %s, %s es %s\n", "manzana",
"pera","naranja",maximum("pera","manzana","naranja"));
}
}
Veamos a nuestro metodo generico para estudiarlo:
public static <T extends Comparable<T>> T maximum(T x, T y, T z)
{
T max = x;
if (y.compareTo(max)>0)
max = y;
if (z.compareTo(max)>0)
max = z;
return max;
}
Vemos como donde esta declarado el tipo de parametro le agregamos la palabra extends y la clase Comparable donde le informaremos nuestro tipo de parametro para luego nombrarlo como maximum y le diremos que comparara tres valores, observen como siempre utilizamos el tipo de parametro, en este caso T, despues en el bloque la primera linea definira a max como x, es decir que asume que el valor de x sera el maximo, luego tendra un condicional donde compara a la variable y con max y en caso de ser mayor a cero reemplaza a max con y, el siguiente condicional compara a z con max y en caso de ser mayor a cero reemplaza a max con z para finalmente devolver el valor asignado a max, despues en el main mostraremos tres lineas por medio de printf, tomemos una de ejemplo porque las tres son iguales:
System.out.printf("Maximo de %d, %d, %d es %d\n\n",
3, 4, 5, maximum( 3, 4, 5));
Tendremos un texto y unos modificadores, en este caso %d el cual se encargara de mostrar valores de tipo entero (integer), pueden ver tres primeros y luego uno separado, en este caso los tres primeros seran los tres numeros que pasamos luego y el cuarto valor sera el valor obtenido de nuestro metodo generico, maximum, lo mismo ocurre con las otras dos lineas, lo unico que cambia es el modificador de printf porque se adecua al tipo de dato que manipulamos, probemos de compilarlo y veamos su salida:
tinchicus@dbn001vrt:~/programacion/java/codigo$ java ValorMaximo
Maximo de 3, 4, 5 es 5
Maximo de 6,6, 7,7, 8,8 es 8,8
Maximo de manzana, pera, naranja es pera
tinchicus@dbn001vrt:~/programacion/java/codigo$
Como pueden ver de los tres valores informados obtendremos siempre el valor maximo, y como en el caso anterior este metodo es muy util a la hora de manipular distintos tipos de informacion, nuestra siguiente parte sera hablar de las clases genericas.
Las clases genericas se declaran de la misma forma que las clases comunes pero con la diferencia de tener el tipo de parametro en el encabezado, al igual que los metodos estas tambien soportan uno o varios tipos de parametros separados por comas, a estas clases se las llama parametrizadas o tipo parametrizadas porque aceptan uno o mas parametros, para entender este concepto veamos el siguiente ejemplo:
Box.java:
public class Box<T>
{
private T t;
public void add(T t)
{
this.t = t;
}
public T get()
{
return t;
}
public static void main(String[] args)
{
Box<Integer> integerBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();
integerBox.add(new Integer(10));
stringBox.add(new String("Hola Mundo!"));
System.out.printf("Valor entero: %d\n\n", integerBox.get());
System.out.printf("Valor cadena: %s\n", stringBox.get());
}
}
En este ejemplo tenemos el tipo de parametro en el encabezado de la clase, < T >, despues crearemos una variable del tipo de parametro llamada t, un metodo encargado de recibir un valor y asignarlo a t, por ultimo otro metodo llamado get que nos devolvera lo que tenga t, en el cuerpo de main crearemos dos objetos derivados de esta clase, uno llamado integerBox y otro stringBox en los cuales a Box le diremos que el tipo de parametro es Integer y String respectivamente, luego por medio de add les asignaremos un valor, como dijimos antes no se pueden usar tipos primitivos sino de referencia, luego por medio de printf traeremos de vuelta los valores enviados, compilemos y probemos el programa para obtener la siguiente salida:
tinchicus@dbn001vrt:~/programacion/java/codigo$ java Box
Valor entero: 10
Valor cadena: Hola Mundo!
tinchicus@dbn001vrt:~/programacion/java/codigo$
Como pueden ver nuestra clase tiene la habilidad de poder procesar distintos tipos de informacion sin necesidad de complementos o clases adicionales, simplemente con un tipo de parametro informado en la declaracion de la clase.
En resumen, hoy hemos visto la base de que es generico, una forma practica para los programadores de tener una clase o un metodo que pueda tener varios usos, un ejemplo de metodo generico, una clase generica y como podemos limitar un metodo generico, espero les haya sido util sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.
Tengo un Patreon donde podes acceder de manera exclusiva a material para este blog antes de ser publicado, sigue los pasos del link para saber como.


Tambien podes donar
Es para mantenimiento del sitio, gracias!
$1.50