Resumen - Contenedor genérico
Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy — lección 58 de 87.
Desafío
Fácil¡Vamos a construir un sistema de almacenamiento versátil que reúna todo lo que has aprendido sobre genéricos! Crearás una clase Container que pueda almacenar, recuperar y procesar elementos de cualquier tipo, junto con métodos de utilidad que demuestren los comodines (wildcards) en acción.
Organizarás tu código en tres archivos:
Container.java: Crea una clase genéricaContainer<T>que gestione una colección de elementos. Tu contenedor debe usar unArrayList<T>internamente para almacenar los elementos. Incluye métodos paraadd(T item)un elemento,get(int index)para recuperar un elemento en una posición específica,size()para devolver la cantidad de elementos eisEmpty()para verificar si el contenedor no tiene elementos. También añade un métodogetAll()que devuelva la lista interna.ContainerUtils.java: Crea una clase de utilidad con métodos genéricos estáticos que funcionen con tus contenedores:printAll(Container<?> container)- Utiliza un comodín sin límites (unbounded wildcard) para imprimir todos los elementos de cualquier contenedor, uno por línea.countItems(Container<? extends Number> container)- Utiliza un comodín con límite superior (upper bounded wildcard) para calcular la suma de todos los valores numéricos en el contenedor, devolviendo el resultado como undouble.addDefaults(Container<? super Integer> container)- Utiliza un comodín con límite inferior (lower bounded wildcard) para añadir los enteros 1, 2 y 3 a cualquier contenedor que pueda contener enteros.<T> T getLastOrDefault(Container<T> container, T defaultValue)- Un método genérico que devuelve el último elemento del contenedor, o el valor por defecto si el contenedor está vacío.Main.java: ¡Une tu sistema de contenedores genéricos! Recibirás tres entradas: una palabra (String), un entero y un double.Primero, crea un
Container<String>y añade la palabra dos veces. ImprimeString container:y luego usaprintAllpara mostrar su contenido.A continuación, crea un
Container<Double>y añádele el valor double. Imprime una línea en blanco, luegoNumber sum: [sum]usandocountItems.Luego crea un
Container<Number>y llama aaddDefaultssobre él. Imprime una línea en blanco, luegoAfter adding defaults:y usaprintAllpara mostrar el contenido.Finalmente, crea un
Container<Integer>vacío y usagetLastOrDefaultcon tu entrada entera como valor por defecto. Imprime una línea en blanco, luegoLast or default: [result].
Recibirás tres entradas en orden: una palabra (String), un entero y un double.
Este desafío combina clases genéricas, métodos genéricos, parámetros de tipo acotados y los tres tipos de comodines. Observa cómo cada pieza cumple un propósito diferente: la clase genérica proporciona almacenamiento seguro para tipos, los comodines acotados permiten lectura y escritura flexibles, ¡y los métodos genéricos ofrecen operaciones reutilizables en diferentes tipos de contenedores!
Pruébalo tú mismo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Leer entradas
String word = scanner.nextLine();
int intValue = Integer.parseInt(scanner.nextLine());
double doubleValue = Double.parseDouble(scanner.nextLine());
// TODO: Crear un Container<String> y añadir la palabra dos veces
// Imprimir "String container:" luego usar ContainerUtils.printAll()
// TODO: Crear un Container<Double> y añadir el valor double
// Imprimir una línea en blanco, luego "Number sum: [sum]" usando ContainerUtils.countItems()
// TODO: Crear un Container<Number> y llamar a ContainerUtils.addDefaults() en él
// Imprimir una línea en blanco, luego "After adding defaults:" y usar ContainerUtils.printAll()
// TODO: Crear un Container<Integer> vacío
// Usar ContainerUtils.getLastOrDefault() con intValue como valor por defecto
// Imprimir una línea en blanco, luego "Last or default: [result]"
}
}
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a la OOPClases vs. ObjetosLa palabra clave thisMétodosCampos (Atributos)Método constructorSobrecarga de constructoresResumen - Calculadora simple4Herencia
Herencia básica (extends)La palabra clave superSobrescritura de métodos (@Override)Encadenamiento de constructoresLa clase ObjectHerencia simple y multinivelPor qué no hay herencia múltiple de clasesResumen - Jerarquía de empleados7Métodos especiales y la clase Object
Método toString()equals() y hashCode()Método clone()compareTo() y ComparableInterfaz ComparatorResumen - Ordenamiento personalizado2Modificadores de acceso y encapsulamiento
Visión general de los niveles de accesoMétodos Getter y SetterOcultamiento de informaciónLa palabra clave finalResumen - Gestor de cuentas bancarias5Polimorfismo
Fundamentos de sobrecarga de métodosSobrescritura de métodos (tiempo de ejecución)Upcasting y DowncastingEl operador instanceofClases y métodos abstractosResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaAgregación vs. ComposiciónClases internas, anidadas y anónimasEnums y métodos de EnumRecords (Java 16+)Clases selladas (Java 17+)11Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón BuilderPatrón ObserverPatrón Strategy3Propiedades de clase y miembros estáticos
Variables de instancia vs. estáticasMétodos estáticosBloques estáticosConstantes (static final)Repaso - Contador y utilidad6Interfaces y Clases Abstractas
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesMétodos Default y Static en InterfacesClases Abstractas vs InterfacesInterfaces FuncionalesResumen - Sistema de Pagos9Genéricos
Introducción a los genéricosClases genéricasMétodos genéricosParámetros de tipo delimitadosComodines (?, extends, super)Resumen - Contenedor genérico12Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Iterator