Wildcard generics in Java provide flexibility in working with generic types by allowing unknown or partially constrained types in method parameters, return types, or fields. They are denoted by the ? symbol and are useful when you need to work with a range of types without specifying an exact type.
Important Concepts of Wildcard Generics
- Purpose: Wildcards allow methods or classes to operate on generic types with unknown or loosely defined type parameters, enhancing flexibility while maintaining type safety.
- Syntax: The ? represents an unknown type, used in places like List<?>, List<? extends T>, or List<? super T>.
- Use Cases: Common in APIs like collections, where methods need to accept a variety of generic types (e.g., List<?> for any list).
Types of Wildcards
Unbounded Wildcard (?)
- Represents any type, equivalent to ? extends Object.
- Used when you don’t care about the specific type but need to work with the generic structure.
- Example: List<?> can hold a List<Integer>, List<String>, etc.
- Limitation: You can’t add elements (except null) because the type is unknown, but you can read as Object.
Upper-Bounded Wildcard (? extends T)
Restricts the type to T or its subtypes.
- Used for read-heavy operations (e.g., iterating over a list of numbers).
- Example: List<? extends Number> accepts List<Integer>, List<Double>, etc.
- Limitation: You can read elements as T (e.g., Number), but you can’t add elements (except null) due to type uncertainty.
Lower-Bounded Wildcard (? super T)
- Restricts the type to T or its supertypes.
- Used for write-heavy operations (e.g., adding elements to a list).
- Example: List<? super Integer> accepts List<Integer>, List<Number>, or List<Object>.
- Limitation: You can add T or its subtypes, but reading yields Object unless you know the exact type.
Program
Demonstrating wildcard generics, focusing on upper- and lower-bounded wildcards
import java.util.ArrayList;
import java.util.List;
public class WildcardDemo {
// Method using upper-bounded wildcard to sum numbers
public static double sumList(List<? extends Number> list) {
double sum = 0.0;
for (Number num : list) {
sum += num.doubleValue();
}
return sum;
}
// Method using lower-bounded wildcard to add integers
public static void addIntegers(List<? super Integer> list, int count) {
for (int i = 1; i <= count; i++) {
list.add(i);
}
}
public static void main(String[] args) {
// Upper-bounded wildcard example
List<Integer> integers = new ArrayList<>(List.of(1, 2, 3));
List<Double> doubles = new ArrayList<>(List.of(1.5, 2.5, 3.5));
System.out.println("Sum of integers: " + sumList(integers)); // 6.0
System.out.println("Sum of doubles: " + sumList(doubles)); // 7.5
// Lower-bounded wildcard example
List<Number> numbers = new ArrayList<>();
List<Object> objects = new ArrayList<>();
addIntegers(numbers, 3);
addIntegers(objects, 2);
System.out.println("Numbers list: " + numbers); // [1, 2, 3]
System.out.println("Objects list: " + objects); // [1, 2]
}
}
/*
Sum of integers: 6.0
Sum of doubles: 7.5
Numbers list: [1, 2, 3]
Objects list: [1, 2]
*/
