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

  1. Parámetros de Tipo: Los genéricos utilizan parámetros de tipo que se especifican entre los símbolos < y >.
  2. Clases Genéricas: Clases que pueden operar sobre cualquier tipo de datos.
  3. Métodos Genéricos: Métodos que pueden operar sobre cualquier tipo de datos.
  4. Interfaces Genéricas: Interfaces que pueden operar sobre cualquier tipo de datos.
  5. 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 tipo T.
  • setContenido(T contenido): Método que acepta un argumento del tipo T.
  • getContenido(): Método que devuelve un valor del tipo T.

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étodo imprimirArray.
  • T[] array: El método acepta un array de cualquier tipo T.

Interfaces Genéricas

Definición de una Interfaz Genérica

public interface Contenedor<T> {
    void agregar(T item);
    T obtener();
}

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 tipo T.
  • ContenedorSimple<T>: Implementa la interfaz genérica Contenedor<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 extienda Number.

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

Módulo 2: Flujo de Control

Módulo 3: Programación Orientada a Objetos

Módulo 4: Programación Orientada a Objetos Avanzada

Módulo 5: Estructuras de Datos y Colecciones

Módulo 6: Manejo de Excepciones

Módulo 7: Entrada/Salida de Archivos

Módulo 8: Multihilo y Concurrencia

Módulo 9: Redes

Módulo 10: Temas Avanzados

Módulo 11: Frameworks y Librerías de Java

Módulo 12: Construcción de Aplicaciones del Mundo Real

© Copyright 2024. Todos los derechos reservados