Los Java generics, también llamados en español genéricos en Java, son una característica que se introdujo en JDK 5.0 y tuvo desde el principio el objetivo de mejorar la seguridad del código, reducir errores y de hacer aplicaciones más robustas. Grosso modo, los Java generics nos permiten escribir clases, interfaces y métodos que tengan la posibilidad de operar con cualquier tipo de dato, lo que proporciona una capa de abstracción sobre los tipos.
El día de hoy queremos mostrarte qué son exactamente los Java generics, cómo funcionan y por qué deberías usarlos en el momento de aprender Java.
¿Por qué usar Java generics?
Previo a la llegada de los Java generics, existía un problema bastante común y era el del riesgo de errores de tipo en tiempos de ejecución. Si por ejemplo tenías una lista de objetos en donde se mezclaban distintos tipos de datos, esto podía generar errores inesperados al intentar acceder a ellos.
Con los generics en Java es posible definir un tipo específico que puede ser usado en una clase o método. Este proceso nos ayuda a mejorar la seguridad de nuestro código y también elimina la necesidad de hacer conversiones explícitas de tipo (llamadas casting).
¿Cómo funcionan los Java generics?
Los Java generics funcionan por medio de clases, interfaces y métodos genéricos. Esto quiere decir que es posible crear o definir una clase, método o interfaz que opere con cualquier tipo de dato, pero sin necesidad de especificar el tipo concreto en el momento de la definición.
Definición de clases genéricas
Las clases genéricas pueden definirse haciendo uso de un parámetro de tipo dentro de ángulos (<>). Dicho parámetro actúa como marcador de posición para un tipo que se especificará cuando se haya instanciado la clase. Veamos:
public class Caja<T> {
private T contenido;
public void setContenido(T contenido) {
this.contenido = contenido;
}
public T getContenido() {
return contenido;
}
}
Para este ejemplo, T es un tipo genérico que será reemplazado por un tipo real, ya sea String, Integer o cualquier otro, al momento en el que se instancie la clase Caja. De este modo, puedes tener una caja que solo acepte números, o bien, una que solo acepte cadenas de texto.
public class Main {
public static void main(String[] args) {
Caja<String> cajaDeTextos = new Caja<>();
cajaDeTextos.setContenido("Hola, Generics!");
System.out.println(cajaDeTextos.getContenido());
Caja<Integer> cajaDeNumeros = new Caja<>();
cajaDeNumeros.setContenido(123);
System.out.println(cajaDeNumeros.getContenido());
}
}
Para este caso, en el momento en que instancias la clase Caja, vas a definir qué tipo de dato va a almacenar (String o Integer), y así Java se encarga del trabajo duro y asegurar que solo ese tipo de dato sea almacenado en la caja.
Métodos genéricos
Del mismo modo que las clases, los objetos en Java también pueden ser genéricos. Es decir, puedes crear métodos que funcionen con cualquier tipo de dato. Veamos un ejemplo para entender mejor esto:
public <T> List<T> convertirArrayALista(T[] array) {
return Arrays.asList(array);
}
En este método tenemos varias partes:
- Declaración del tipo genérico
<T>
:- La parte importante del método genérico es la declaración
<T>
justo antes del tipo de retornoList<T>
. Esta declaración le indica al compilador que el método utilizará un tipo genéricoT
, que puede ser cualquier tipo de objeto (comoInteger
,String
,Double
, etc.). T
es un nombre de marcador que representa el tipo genérico y puedes usar cualquier otra letra o palabra pero, por convención, se usaT
(de «Type»).
- La parte importante del método genérico es la declaración
- Parámetro del método:
- El método recibe como parámetro un array de tipo genérico (
T[] array
), lo que significa que puede aceptar un array de cualquier tipo, siempre que ese tipo esté determinado en la llamada al método. Por ejemplo, podría ser un array deString[]
,Integer[]
, etc.
- El método recibe como parámetro un array de tipo genérico (
- Tipo de retorno:
- El método devuelve una lista del mismo tipo genérico (
List<T>
), es decir, la lista que se devolverá contendrá elementos del mismo tipo que el array que recibió como parámetro.
- El método devuelve una lista del mismo tipo genérico (
- Conversión del array a una lista:
- En el cuerpo del método se utiliza
Arrays.asList(array)
, que es un método estándar de Java que convierte un array en una lista. Como el array es del tipoT[]
, la lista resultante será del tipoList<T>
, esto nos hace asegurarnos que tanto el array como la lista contengan el mismo tipo de elementos.
- En el cuerpo del método se utiliza
Java generics con límites
Vas a encontrar que en ocasiones es necesario restringir los tipos de datos que se pueden usar en un tipo genérico. Para esto se usan los límites. Un tipo genérico puede restringirse a a que se extienda a una clase específica o simplemente una interfaz:
public <T extends Number> void imprimirNumeros(T[] numeros) {
for (T numero : numeros) {
System.out.println(numero);
}
}
Este método genérico solo funcionará con clases que extiendan Number, como Integer, Double, o Float.
Si te interesó el tema de los Java Generics y quieres seguir aprendiendo sobre el ecosistema Java, tenemos un bootcamp que te sacará de tu zona de confort al enseñarte cosas únicas. Se trata de nuestro curso java, en donde, en poco tiempo, aprenderás miles de cosas que no imaginaste sobre el lenguaje de programación más popular en todo el mundo. Entenderás por qué su fama no es gratuita, al comprender todas sus herramientas y la cantidad de posibilidades que tienes gracias a este lenguaje. Te ayudaremos a formar tu carrera y entrar en la mejor industria tecnológica. ¡Únete a nosotros ahora!