Wildcards con límite superior
? extends T para productores
Wildcards con límite superior es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.
Los genéricos son invariantes
En Java, los genéricos son invariantes. Un List<Integer> no es un List<Number>, aunque Integer sea un Number.
Esto sorprende a quienes empiezan, pero mantiene coherente el sistema de tipos. Los comodines permiten relajar esta restricción de forma segura.
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> ints = List.of(1, 2, 3);
// List<Number> nums = ints; // would NOT compile
System.out.println("List<Integer> is not List<Number>");
System.out.println(ints);
}
}El comodín con límite superior
? extends T es un comodín con límite superior. Significa "algún tipo desconocido que es T o un subtipo de T".
List<? extends Number> puede hacer referencia a un List<Integer>, un List<Double> o un List<Number>.
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? extends Number> a = List.of(1, 2, 3);
List<? extends Number> b = List.of(1.5, 2.5);
System.out.println(a.get(0));
System.out.println(b.get(0));
}
}Leer de un productor
Con ? extends Number puede leer elementos de forma segura como Number.
Sea cual sea el tipo real de los elementos, se garantiza que es como mínimo un Number, por lo que la lectura es segura para el sistema de tipos.
import java.util.List;
public class Main {
static double sum(List<? extends Number> list) {
double total = 0;
for (Number n : list) total += n.doubleValue();
return total;
}
public static void main(String[] args) {
System.out.println(sum(List.of(1, 2, 3)));
System.out.println(sum(List.of(1.5, 2.5)));
}
}No se puede escribir en ella
Esta es la particularidad: no puede añadir elementos a una lista ? extends Number (excepto null).
El compilador no conoce el tipo exacto de los elementos. Podría ser una List<Integer>, por lo que añadir un Double no sería seguro.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? extends Number> list = new ArrayList<Integer>();
// list.add(1); // does NOT compile
// list.add(1.5); // does NOT compile
System.out.println("Cannot add to ? extends Number");
System.out.println("size = " + list.size());
}
}Por qué está prohibido escribir
Imagine que estuviera permitido. Podría pasar una List<Integer> como List<? extends Number> y después añadir un Double.
El código posterior, al leer la lista como List<Integer>, produciría una ClassCastException. El compilador evita esto prohibiendo las escrituras.
import java.util.List;
public class Main {
public static void main(String[] args) {
// Conceptual: this is why add is blocked
System.out.println("Writing a Double into a List<Integer> would corrupt it");
System.out.println("so ? extends bans all adds");
}
}Caso de uso del productor
Use ? extends T cuando un método solo produzca valores para usted (es decir, cuando los lea).
Un método que copia elementos de una colección de origen es un ejemplo perfecto.
import java.util.ArrayList;
import java.util.List;
public class Main {
static List<Number> copyOut(List<? extends Number> source) {
List<Number> dest = new ArrayList<>();
for (Number n : source) dest.add(n);
return dest;
}
public static void main(String[] args) {
System.out.println(copyOut(List.of(1, 2, 3)));
}
}Parámetros de tipo acotados frente a comodines
No confunda <T extends Number> (un parámetro de tipo acotado) con ? extends Number (un comodín).
- Parámetro de tipo: asigna un nombre al tipo para usarlo en todo el método.
- Comodín: un subtipo anónimo y desconocido, que se usa cuando no es necesario asignarle un nombre.
import java.util.List;
public class Main {
static <T extends Number> T first(List<T> list) { return list.get(0); }
public static void main(String[] args) {
Integer i = first(List.of(10, 20));
System.out.println(i);
}
}Múltiples límites
Un parámetro de tipo puede tener varios límites mediante &, como en <T extends Number & Comparable<T>>.
Los comodines solo admiten un límite superior, por lo que para usar varios límites se necesita un parámetro de tipo con nombre.
import java.util.List;
public class Main {
static <T extends Number & Comparable<T>> T max(List<T> list) {
T best = list.get(0);
for (T t : list) if (t.compareTo(best) > 0) best = t;
return best;
}
public static void main(String[] args) {
System.out.println(max(List.of(3, 9, 1, 7)));
}
}Comodines con Collections.max
El JDK utiliza ampliamente los límites superiores. Por ejemplo, para sumar o recorrer una colección de solo lectura.
Aquí buscamos el elemento más grande de una lista tipada como productor.
import java.util.List;
public class Main {
static double largest(List<? extends Number> nums) {
double max = Double.NEGATIVE_INFINITY;
for (Number n : nums) max = Math.max(max, n.doubleValue());
return max;
}
public static void main(String[] args) {
System.out.println(largest(List.of(4, 2, 9, 1)));
System.out.println(largest(List.of(0.5, 9.9, 3.3)));
}
}null es el único valor que se puede escribir
Lo único que puede añadir a una colección ? extends T es null, porque null se puede asignar a cualquier tipo de referencia.
Esto rara vez resulta útil, pero explica por qué add no está completamente prohibido, sino que en la práctica no se puede usar.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? extends Number> list = new ArrayList<Number>();
// Only null is assignable; demonstrated conceptually
System.out.println("Only null could be added; we avoid that");
System.out.println("size = " + list.size());
}
}Leer como Object siempre funciona
Como todo tipo extiende Object, siempre puede leer los elementos de cualquier lista con comodín como Object.
Con un límite superior de Number, obtiene además la ventaja de poder leerlos directamente como Number.
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? extends Number> nums = List.of(1, 2.0, 3L);
for (Object o : nums) System.out.println(o.getClass().getSimpleName());
}
}Comprobación rápida
Compruebe si entiende los límites superiores.
Resumen
Ha aprendido los comodines con límite superior:
? extends Tsignifica un subtipo desconocido de T.- Puede leer los elementos como T (es un productor).
- No puede añadir elementos que no sean
null. - Los tipos genéricos son invariantes, y los comodines relajan esta restricción de forma segura.
A continuación, la imagen especular: los comodines con límite inferior.
import java.util.List;
public class Main {
public static void main(String[] args) {
List<? extends Number> nums = List.of(1, 2, 3);
System.out.println("Upper bound recap: read " + nums.get(0));
}
}Preguntas frecuentes
¿La lección «Wildcards con límite superior» es gratis?
Sí — el texto completo de «Wildcards con límite superior» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Wildcards con límite superior»?
? extends T para productores Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Java Academy?
No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.
¿Cuánto tiempo toma la lección «Wildcards con límite superior»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Java Academy?
Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Wildcards con límite superior
- Wildcards con límite inferior
- El principio PECS
- Wildcards en APIs