Introducción
Los genéricos en Java permiten que las clases, interfaces y métodos operen sobre tipos especificados por el usuario, proporcionando una forma de reutilizar el código y mejorar la seguridad del tipo en tiempo de compilación. Los genéricos son una característica poderosa que ayuda a evitar errores de tipo y a escribir código más limpio y mantenible.
Conceptos Clave
- Parámetros de Tipo: Los genéricos utilizan parámetros de tipo que se especifican entre los símbolos
<y>. - Clases Genéricas: Clases que pueden operar sobre cualquier tipo de datos.
- Métodos Genéricos: Métodos que pueden operar sobre cualquier tipo de datos.
- Interfaces Genéricas: Interfaces que pueden operar sobre cualquier tipo de datos.
- Tipos Comodín: Representan un tipo desconocido y se denotan con
?.
Clases Genéricas
Definición de una Clase Genérica
public class Caja<T> {
private T contenido;
public void setContenido(T contenido) {
this.contenido = contenido;
}
public T getContenido() {
return contenido;
}
}Uso de una Clase Genérica
public class Main {
public static void main(String[] args) {
Caja<String> cajaDeString = new Caja<>();
cajaDeString.setContenido("Hola Mundo");
System.out.println(cajaDeString.getContenido());
Caja<Integer> cajaDeInteger = new Caja<>();
cajaDeInteger.setContenido(123);
System.out.println(cajaDeInteger.getContenido());
}
}Explicación
Caja<T>: Define una clase genérica con un parámetro de tipoT.setContenido(T contenido): Método que acepta un argumento del tipoT.getContenido(): Método que devuelve un valor del tipoT.
Métodos Genéricos
Definición de un Método Genérico
public class Util {
public static <T> void imprimirArray(T[] array) {
for (T elemento : array) {
System.out.print(elemento + " ");
}
System.out.println();
}
}Uso de un Método Genérico
public class Main {
public static void main(String[] args) {
Integer[] arrayDeEnteros = {1, 2, 3, 4, 5};
String[] arrayDeStrings = {"A", "B", "C"};
Util.imprimirArray(arrayDeEnteros);
Util.imprimirArray(arrayDeStrings);
}
}Explicación
<T>: Define un parámetro de tipo genérico para el métodoimprimirArray.T[] array: El método acepta un array de cualquier tipoT.
Interfaces Genéricas
Definición de una Interfaz Genérica
Implementación de una Interfaz Genérica
public class ContenedorSimple<T> implements Contenedor<T> {
private T item;
@Override
public void agregar(T item) {
this.item = item;
}
@Override
public T obtener() {
return item;
}
}Uso de una Interfaz Genérica
public class Main {
public static void main(String[] args) {
Contenedor<String> contenedorDeString = new ContenedorSimple<>();
contenedorDeString.agregar("Hola");
System.out.println(contenedorDeString.obtener());
Contenedor<Integer> contenedorDeInteger = new ContenedorSimple<>();
contenedorDeInteger.agregar(123);
System.out.println(contenedorDeInteger.obtener());
}
}Explicación
Contenedor<T>: Define una interfaz genérica con un parámetro de tipoT.ContenedorSimple<T>: Implementa la interfaz genéricaContenedor<T>.
Tipos Comodín
Uso de Tipos Comodín
public class Util {
public static void imprimirLista(List<?> lista) {
for (Object elemento : lista) {
System.out.print(elemento + " ");
}
System.out.println();
}
}Uso de Tipos Comodín con Bounded Wildcards
public class Util {
public static void imprimirListaDeNumeros(List<? extends Number> lista) {
for (Number numero : lista) {
System.out.print(numero + " ");
}
System.out.println();
}
}Explicación
List<?>: Representa una lista de cualquier tipo.List<? extends Number>: Representa una lista de cualquier tipo que extiendaNumber.
Ejercicios Prácticos
Ejercicio 1: Clase Genérica
Instrucciones: Crea una clase genérica Par que almacene dos valores de cualquier tipo.
public class Par<T, U> {
private T primero;
private U segundo;
public Par(T primero, U segundo) {
this.primero = primero;
this.segundo = segundo;
}
public T getPrimero() {
return primero;
}
public U getSegundo() {
return segundo;
}
}Solución:
public class Main {
public static void main(String[] args) {
Par<String, Integer> par = new Par<>("Edad", 30);
System.out.println("Primero: " + par.getPrimero());
System.out.println("Segundo: " + par.getSegundo());
}
}Ejercicio 2: Método Genérico
Instrucciones: Crea un método genérico intercambiar que intercambie dos elementos en un array.
public class Util {
public static <T> void intercambiar(T[] array, int i, int j) {
T temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}Solución:
public class Main {
public static void main(String[] args) {
Integer[] array = {1, 2, 3, 4, 5};
Util.intercambiar(array, 0, 4);
for (int i : array) {
System.out.print(i + " ");
}
}
}Conclusión
En esta sección, hemos explorado los conceptos fundamentales de los genéricos en Java, incluyendo clases, métodos e interfaces genéricas, así como el uso de tipos comodín. Los genéricos son una herramienta poderosa para escribir código más flexible y seguro. Asegúrate de practicar con los ejercicios proporcionados para consolidar tu comprensión de estos conceptos. En el próximo tema, profundizaremos en las anotaciones en Java.
Curso de Programación en Java
Módulo 1: Introducción a Java
- Introducción a Java
- Configuración del Entorno de Desarrollo
- Sintaxis y Estructura Básica
- Variables y Tipos de Datos
- Operadores
Módulo 2: Flujo de Control
Módulo 3: Programación Orientada a Objetos
- Introducción a la POO
- Clases y Objetos
- Métodos
- Constructores
- Herencia
- Polimorfismo
- Encapsulamiento
- Abstracción
Módulo 4: Programación Orientada a Objetos Avanzada
Módulo 5: Estructuras de Datos y Colecciones
Módulo 6: Manejo de Excepciones
- Introducción a las Excepciones
- Bloque Try-Catch
- Throw y Throws
- Excepciones Personalizadas
- Bloque Finally
Módulo 7: Entrada/Salida de Archivos
- Lectura de Archivos
- Escritura de Archivos
- Flujos de Archivos
- BufferedReader y BufferedWriter
- Serialización
Módulo 8: Multihilo y Concurrencia
- Introducción al Multihilo
- Creación de Hilos
- Ciclo de Vida de un Hilo
- Sincronización
- Utilidades de Concurrencia
Módulo 9: Redes
- Introducción a las Redes
- Sockets
- ServerSocket
- DatagramSocket y DatagramPacket
- URL y HttpURLConnection
